Cloud Endpoints 接受一组特定于 Google 的 OpenAPI 规范扩展程序,用于配置 Extensible Service Proxy (ESP)、Extensible Service Proxy V2 (ESPv2) 和 Service Control 的行为。本页介绍了特定于 Google 的 OpenAPI 规范扩展程序。
尽管下面提供的示例采用了 YAML 格式,但也支持 JSON。
命名惯例
Google OpenAPI 扩展程序的名称以 x-google-
前缀开头。
x-google-allow
x-google-allow: [configured | all]
此扩展程序用于 OpenAPI 规范的顶层,可用来指示应允许哪些网址路径通过 ESP。
可能的值有 configured
和 all
。
默认值为 configured
,这表示只有您在 OpenAPI 规范中列出的 API 方法可通过 ESP 提供。
如果使用 all
,则未配置的调用(无论是否使用 API 密钥或用户身份验证)会通过 ESP 传递给您的 API。
ESP 以区分大小写的方式处理对 API 的调用。
例如,ESP 将 /widgets
和 /Widgets
视为不同的 API 方法。
使用 all
时,您需要特别注意以下两个方面:
- 任何 API 密钥或身份验证规则。
- 服务中的后端路径路由。
我们建议您将 API 配置为使用区分大小写的路径路由,这是一种最佳做法。在使用区分大小写的路由后,如果网址中请求的方法与 OpenAPI 规范中列出的 API 方法名称不匹配,您的 API 会返回 HTTP 状态代码 404
。请注意,Node.js Express 等 Web 应用框架有一项设置用于启用或停用区分大小写的路由。默认行为取决于您所使用的框架。建议您查看框架中的设置,以确保启用区分大小写的路由。这一建议符合 OpenAPI 规范 2.0 版,该规范指出:“规范中的所有字段名称都区分大小写”。
示例
假设:
x-google-allow
设置为all
。- OpenAPI 规范中列有 API 方法
widgets
,而非Widgets
。 - 您已将 OpenAPI 规范配置为需要 API 密钥。
由于 OpenAPI 规范中列有 widgets
,因此 ESP 会阻止以下请求,因为该请求不具有 API 密钥:
https://my-project-id.appspot.com/widgets
由于 OpenAPI 规范中未列出 Widgets
,因此 ESP 会将以下请求传递给您的服务,而无需 API 密钥:
https://my-project-id.appspot.com/Widgets/
如果 API 使用区分大小写的路由(并且您未将对“Widgets”的调用路由到任何代码),则 API 后端将返回 404
。不过,如果您使用不区分大小写的路由,则 API 后端会将此调用路由到“widgets”。
不同的语言和框架采用不同的方法来控制大小写区分和路由。如需了解详情,请参阅框架的相关文档。
x-google-backend
x-google-backend
扩展程序指定如何将请求路由到本地后端或远程后端。可以在 OpenAPI 规范的顶层和/或操作级别指定扩展程序。
默认情况下,ESP 配置为将所有流量代理至单个本地后端。本地后端地址由 --backend
标志(默认为 http://127.0.0.1:8081
)指定。您可以使用 x-google-backend
扩展程序替换此默认行为,并指定可接收请求的一个或多个本地后端或远程后端。
x-google-backend
扩展程序还可以为本地后端和远程后端配置其他设置,例如身份验证和超时。所有这些配置都可以按照每项操作的方式应用。
x-google-backend
扩展程序包含以下字段:
address
address: URL
可选。目标后端的网址。
该网址所用架构必须是 http
或 https
。
路由到远程后端(无服务器)时,应设置此网址,其架构部分应为 https
。
如果操作使用 x-google-backend
,但未指定 address
,则 ESPv2 会将请求路由到 --backend
标志指定的本地后端。
jwt_audience | disable_auth
这两项属性只能设置其中一项。
如果操作使用 x-google-backend
,但未指定 jwt_audience
或 disable_auth
,则 ESPv2 将自动默认使用 jwt_audience
以匹配 address
。如果未设置 address
,则 ESPv2 会自动将 disable_auth
设置为 true
。
jwt_audience
jwt_audience: string
可选。ESPv2 获取实例 ID 令牌时指定的 JWT 目标对象,然后供发出目标后端请求时使用。
配置无服务器端点时,远程后端应配置为仅允许来自 ESPv2 的流量。在代理请求时,ESPv2 会将实例 ID 令牌附加到 Authorization
标头。实例 ID 令牌代表用于部署 ESPv2 的运行时服务账号。随后,远程后端可以根据附加的令牌来验证请求是否来自 ESPv2。
例如,部署在 Cloud Run 上的远程后端可以使用 IAM 执行以下操作:
- 通过撤消特殊
allUsers
主账号中的roles/run.invoker
来限制未经身份验证的调用。 - 通过向 ESPv2 运行时服务账号授予
roles/run.invoker
角色,仅允许 ESPv2 调用后端。
默认情况下,ESPv2 会创建一个实例 ID 令牌,其 JWT 目标对象与 address
字段匹配。仅当目标后端使用基于 JWT 的身份验证且预期目标与 address
字段中指定的值不同时,才需要手动指定 jwt_audience
。对于部署在 App Engine 上或使用 IAP 的远程后端,您必须替换 JWT 目标对象。App Engine 和 IAP 使用其 OAuth 客户端 ID 作为预期目标对象。
启用此功能后,ESPv2 将更改请求中的标头。如果请求已设置 Authorization
标头,则 ESPv2 将执行以下操作:
- 将原始值复制到新标头
X-Forwarded-Authorization
。 - 将
Authorization
标头替换为实例 ID 令牌。
因此,如果 API 客户端设置了 Authorization
标头,则在 ESPv2 后运行的后端应使用 X-Forwarded-Authorization
标头来检索整个 JWT。后端必须验证此标头中的 JWT,因为如果未配置身份验证方法,ESPv2 将不会执行验证。
disable_auth
disable_auth: bool
可选。此属性确定 ESPv2 是否应禁止获取实例 ID 令牌并阻止将其附加到请求中。
在配置目标后端时,如果满足以下任一条件,您可能不想使用 IAP 或 IAM 对来自 ESPv2 的请求进行身份验证:
- 后端应允许未经身份验证的调用。
- 后端需要 API 客户端的原始
Authorization
标头,并且不能使用X-Forwarded-Authorization
(如jwt_audience
部分所述)。
在这种情况下,请将此字段设为 true
。
path_translation
path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]
可选。设置在将请求发送到目标后端时,ESPv2 使用的路径转换策略。
如需详细了解路径转换,请参阅了解路径转换部分。
当 x-google-backend
用于 OpenAPI 规范的顶层时,path_translation
默认为 APPEND_PATH_TO_ADDRESS
;而当 x-google-backend
用于 OpenAPI 规范的操作级层时,path_translation
默认为 CONSTANT_ADDRESS
。如果无 address
字段,则 path_translation
将处于未指定状态,并且不会发生相应的操作。
deadline
deadline: double
可选。等待请求完整响应的秒数。
超过配置的截止期限的响应会超时。
默认截止期限为 15.0
秒。
系统不接受非正值。在这些情况下,ESPv2 会自动使用默认值。
无法停用截止期限,但可以将其设置为较高的数字,例如 3600.0
表示一小时。
protocol
protocol: [ http/1.1 | h2 ]
可选。用于向后端发送请求的协议。
支持的值为 http/1.1
和 h2
。
HTTP 和 HTTPS 后端的默认值为 http/1.1
。
对于支持 HTTP/2 的安全 HTTP 后端 (https://),请将此字段设置为 h2
以提升性能。 对于 Google Cloud 无服务器后端,这是推荐的选项。
在 ESP 中启用后端支持
ESPv2 将会自动检测何时配置了 x-google-backend
。
ESP 需要手动更改配置才能启用此功能。要在 ESP 中启用 x-google-backend
支持,请在运行 ESP 容器时提供 --enable_backend_routing
参数。
(对于您无法控制 ESP 容器选项的运行时,系统已为您提供此选项。)下面的示例展示了如何在将 ESP 容器部署到 GKE 时启用 x-google-backend
支持(此示例基于“GKE 上的 Endpoints”教程示例构建):
- name: esp image: gcr.io/endpoints-release/endpoints-runtime:1 args: [ "--http_port", "8081", "--service", "SERVICE_NAME", "--rollout_strategy", "managed", "--enable_backend_routing" ]
了解路径转换
当 ESP 处理请求时,它将采用原始请求路径并对其进行转换,然后才会向目标后端发出请求。至于这种转换具体是如何发生的,则取决于您所使用的路径转换策略。有两种路径转换策略:
APPEND_PATH_TO_ADDRESS
:将原始请求路径附加到x-google-backend
扩展程序的address
网址,借此计算目标后端请求路径。CONSTANT_ADDRESS
:目标请求路径是常量,由x-google-backend
扩展程序的address
网址定义。如果相应的 OpenAPI 路径包含参数,则参数名称及其值会变为查询参数。
示例:
APPEND_PATH_TO_ADDRESS
address: https://my-project-id.appspot.com/BASE_PATH
- 带 OpenAPI 路径参数
- OpenAPI 路径:
/hello/{name}
- 请求路径:
/hello/world
- 目标请求网址:
https://my-project-id.appspot.com/BASE_PATH/hello/world
- OpenAPI 路径:
- 不带 OpenAPI 路径参数
- OpenAPI 路径:
/hello
- 请求路径:
/hello
- 目标请求网址:
https://my-project-id.appspot.com/BASE_PATH/hello
- OpenAPI 路径:
CONSTANT_ADDRESS
address
:https://us-central1-my-project-id.cloudfunctions.net/helloGET
- 带 OpenAPI 路径参数
- OpenAPI 路径:
/hello/{name}
- 请求路径:
/hello/world
- 目标请求网址:
https://us-central1-my-project-id.cloudfunctions.net/helloGET?name=world
- OpenAPI 路径:
- 不带 OpenAPI 路径参数
- OpenAPI 路径:
/hello
- 请求路径:
/hello
- 目标请求网址:
https://us-central1-my-project-id.cloudfunctions.net/helloGET
- OpenAPI 路径:
x-google-endpoints
本部分介绍 x-google-endpoints
扩展程序的用法。
在 cloud.goog
网域上配置 DNS
如果您已将应用部署到 Compute Engine 或 Google Kubernetes Engine,则可以为 cloud.goog
网域上的 Endpoints 服务创建 DNS 条目,具体方法是向 OpenAPI 文档添加以下内容:
x-google-endpoints: - name: "API_NAME.endpoints.PROJECT_ID.cloud.goog" target: "IP_ADDRESS"
在 OpenAPI 文档的顶层添加 x-google-endpoints
扩展程序(不缩进或嵌套)。您必须按以下格式配置域名:.endpoints.PROJECT_ID.cloud.goog
例如:
swagger: "2.0" host: "my-cool-api.endpoints.my-project-id.cloud.goog" x-google-endpoints: - name: "my-cool-api.endpoints.my-project-id.cloud.goog" target: "192.0.2.1"
.cloud.goog
是由 Google 管理的网域,可供 Google Cloud 客户共用。由于 Google Cloud 项目 ID 在全局范围内不会重复,因此 .endpoints.PROJECT_ID.cloud.goog
格式的域名是您的 API 的专属域名。
为简单起见,请将 host
字段和 x-google-endpoints.name
字段配置为相同的值。部署 OpenAPI 文档时,Service Management 会创建以下内容:
- 托管式服务(使用您在
host
字段中指定的名称)。 - DNS A 记录(使用您在
x-google-endpoints
扩展程序中配置的名称和 IP 地址)。
对于在 App Engine 柔性环境中托管的 API,您可以使用 appspot.com
网域。如需了解详情,请参阅配置 Endpoints。
配置 ESP 以允许 CORS 请求
如果从不同来源的网页应用调用您的 API,您的 API 必须支持跨源资源共享 (CORS)。如需了解如何配置 ESP 以支持 CORS,请参阅向 ESP 添加 CORS 支持。
如果您需要在后端代码中实现自定义 CORS 支持,请设置 allowCors: True
,这样 ESP 便可将所有 CORS 请求传递到您的后端代码:
x-google-endpoints: - name: "API_NAME.endpoints.PROJECT_ID.cloud.goog" allowCors: True
请在 OpenAPI 文档的顶层(不使用缩进或嵌套结构)添加 x-google-endpoints
扩展程序,例如:
swagger: "2.0" host: "my-cool-api.endpoints.my-project-id.cloud.goog" x-google-endpoints: - name: "my-cool-api.endpoints.my-project-id.cloud.goog" allowCors: True
x-google-issuer
x-google-issuer: URI | EMAIL_ADDRESS
此扩展程序用于 OpenAPI securityDefinitions
部分,可用来指定凭据的签发者。值可以采用主机名或电子邮件地址的形式。
x-google-jwks_uri
x-google-jwks_uri: URI
提供商公钥集的 URI,用于验证 JSON Web 令牌的签名。
ESP 支持 x-google-jwks_uri
OpenAPI 扩展定义的两种非对称公钥格式:
-
JWK 集格式。
例如:
x-google-jwks_uri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
-
X509。例如:
x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
如果您使用的是对称密钥格式,请将 x-google-jwks_uri
设置为包含 base64url 编码密钥字符串的文件的 URI。
如果省略 x-google-jwks_uri
,ESP 将遵循 OpenID Connect Discovery 协议自动发现给定 OpenID 提供商的 JWKS URI。ESP 将向 x-google-issuer/.well-known/openid-configuration
发送请求,解析 JSON 响应,以及从顶级 jwks_uri
字段读取 JWKS URI。
请注意,省略 x-google-jwks_uri
会导致较长的冷启动时间,因为 ESP 必须在启动时进行额外的远程调用。因此,如果 JWKS URI 经常发生更改,建议您仅省略此字段。
大多数认证的 OpenID 提供商(例如 Google、Auth0 和 Okta)拥有稳定的 JWKS URI。
x-google-jwt-locations
默认情况下,JWT 会在 Authorization
标头(以 "Bearer "
为前缀)、X-Goog-Iap-Jwt-Assertion
标头或 access_token
查询参数中传递。有关传递 JWT 的示例,请参阅向 Endpoints API 发出经过身份验证的调用。
或者,您也可以使用 OpenAPI SecurityDefinitions 部分中的 x-google-jwt-locations
扩展程序,以提供从中提取 JWT 令牌的自定义位置。
x-google-jwt-locations
扩展程序接受 JWT 位置列表。每个 JWT 位置都包含以下字段:
元素 | 说明 |
---|---|
header/query |
必需。包含 JWT 的标头的名称,或包含 JWT 的查询参数的名称。 |
value_prefix |
可选。仅适用于标头。设置 value_prefix 时,其值必须与包含 JWT 的标头值的前缀匹配。
|
例如:
x-google-jwt-locations:
# Expect header "Authorization": "MyBearerToken <TOKEN>"
- header: "Authorization"
value_prefix: "MyBearerToken "
# expect header "jwt-header-foo": "jwt-prefix-foo<TOKEN>"
- header: "jwt-header-foo"
value_prefix: "jwt-prefix-foo"
# expect header "jwt-header-bar": "<TOKEN>"
- header: "jwt-header-bar"
# expect query parameter "jwt_query_bar=<TOKEN>"
- query: "jwt_query_bar"
如果您希望仅支持部分默认 JWT 位置,请在 x-google-jwt-locations
扩展程序中明确列出这些位置。例如,要仅添加对带有 "Bearer "
前缀的 Authorization
标头的支持,请使用以下命令:
x-google-jwt-locations:
# Support the default header "Authorization": "Bearer <TOKEN>"
- header: "Authorization"
value_prefix: "Bearer "
x-google-audiences
x-google-audiences: STRING
此扩展程序用于 OpenAPI securityDefinitions
部分,可用来提供 JWT aud
字段在 JWT 身份验证期间应与之匹配的受众群体列表。此扩展程序接受单个字符串,其中的各个值需要用英文逗号分隔开。受众群体之间不允许有空格。如果未指定,JWT aud
字段应与 OpenAPI 文档中的 host
字段匹配,除非使用标志 --disable_jwt_audience_service_name_check
。如果使用此标志且未指定 x-google-audiences
,则 JWT aud
字段不会被选中。
securityDefinitions: google_id_token: type: oauth2 authorizationUrl: "" flow: implicit x-google-issuer: "https://accounts.google.com" x-google-jwks_uri: "https://www.googleapis.com/oauth2/v1/certs" x-google-audiences: "848149964201.apps.googleusercontent.com,841077041629.apps.googleusercontent.com"
x-google-management
x-google-management
扩展程序可控制 API 管理的不同方面,并包含本部分中描述的字段。
metrics
您可以将 metrics
与配额和 x-google-quota
结合使用,以便为您的 API 配置配额。通过配额,您可以控制应用调用 API 中的方法的速率。例如:
x-google-management:
metrics:
- name: read-requests
displayName: Read requests
valueType: INT64
metricKind: DELTA
metrics
字段包含具有以下键值对的列表:
元素 | 说明 |
---|---|
name | 必需。此指标的名称。通常,这是对指标进行唯一标识的请求类型(例如“read-requests”或“write-requests”)。 |
displayName | 可选,但建议填写。此文本会显示在 Google Cloud 控制台中 Endpoints > Services 页面的配额标签页上,用于标识指标。您的 API 使用方还会在 IAM 和管理与 API 和服务下的配额页面上看到此文本。显示名不得超过 40 个字符。 为确保可读性,相关配额限制中的单位会自动附加到 Google Cloud 控制台中的显示名称末尾。例如,如果您为显示名称指定“Read requests”,则 Google Cloud 控制台中会显示“Read requests per minute per project”。如果未指定,则系统会在 IAM 和管理员与 API 和服务下的配额页面上向 API 的使用方显示“unlabeled quota”。 为了与 API 使用方在配额页面上看到的 Google 服务显示名保持一致,我们针对显示名提出以下建议:
|
valueType | 必需。必须是 INT64 |
metricKind | 必需。必须为 DELTA |
quota
您可以在 quota
部分中为定义的指标指定配额限制。例如:
quota:
limits:
- name: read-requests-limit
metric: read-requests
unit: 1/min/{project}
values:
STANDARD: 5000
quota.limits
字段包含具有以下键值对的列表:
元素 | 说明 |
---|---|
name | 必需。限制的名称,该名称在服务中必须是唯一的。该名称可以包含大小写字母、数字和“-”(短划线字符),并且长度不得超过 64 个字符。 |
metric | 必需。此限制所适用的指标的名称。此名称必须与指标名称中指定的文本匹配。如果指定的文本与指标名称不匹配,那么在您部署 OpenAPI 文档时会出现错误。 |
unit | 必需。限制的单位。目前仅支持“1/min/{project}”,这表示系统会对每个项目强制执行该限制,并且会每分钟重置一次用量。 |
values | 必需。指标的限制。您必须将其指定为键值对,格式如下:STANDARD: YOUR-LIMIT-FOR-THE-METRIC YOUR-LIMIT-FOR-THE-METRIC 替换为整数值,该整数值是针对指定单位(目前只能是每个项目每分钟)所允许的最大请求次数。例如:values: STANDARD: 5000 |
x-google-quota
x-google-quota
扩展程序用于 OpenAPI paths
部分,可用来将 API 中的方法与指标相关联。未定义 x-google-quota
的方法没有应用配额限制。例如:
x-google-quota:
metricCosts:
read-requests: 1
x-google-quota
扩展程序包含以下项:
元素 | 说明 |
---|---|
metricCosts | 用户定义的键值对:"YOUR-METRIC-NAME": METRIC-COST 。
|
配额示例
以下示例展示了如何为读取请求和写入请求添加指标和限制。
x-google-management:
metrics:
# Define a metric for read requests.
- name: "read-requests"
displayName: "Read requests"
valueType: INT64
metricKind: DELTA
# Define a metric for write requests.
- name: "write-requests"
displayName: "Write requests"
valueType: INT64
metricKind: DELTA
quota:
limits:
# Rate limit for read requests.
- name: "read-requests-limit"
metric: "read-requests"
unit: "1/min/{project}"
values:
STANDARD: 5000
# Rate limit for write requests.
- name: "write-request-limit"
metric: "write-requests"
unit: "1/min/{project}"
values:
STANDARD: 5000
paths:
"/echo":
post:
description: "Echo back a given message."
operationId: "echo"
produces:
- "application/json"
responses:
200:
description: "Echo"
schema:
$ref: "#/definitions/echoMessage"
parameters:
- description: "Message to echo"
in: body
name: message
required: true
schema:
$ref: "#/definitions/echoMessage"
x-google-quota:
metricCosts:
read-requests: 1
security:
- api_key: []
x-google-api-name
如果您的服务仅包含一个 API,则该 API 名称与 Endpoints 服务名称相同。(Endpoints 使用您在 OpenAPI 文档的 host
字段中指定的名称作为您的服务的名称)。如果您的服务包含多个 API,那么您需要向 OpenAPI 文档添加 x-google-api-name
扩展程序,以指定 API 名称。借助 x-google-api-name
扩展程序,您可以明确地为各个 API 命名,并对每个 API 进行独立的版本控制。
例如,您可以使用下面的 OpenAPI 文档片段来配置名为 api.example.com
且包含两个 API(Producer 和 Consumer)的服务:
producer.yaml
中的 Producer API:swagger: 2.0 host: api.example.com x-google-api-name: producer info: version: 1.0.3
consumer.yaml
中的 Consumer API:swagger: 2.0 host: api.example.com x-google-api-name: consumer info: version: 1.1.0
您可以使用以下命令同时部署这两个 OpenAPI 文档:
gcloud endpoints services deploy producer.yaml consumer.yaml