API Gateway 中的 OpenAPI 2.0 扩展程序
API Gateway 接受一组特定于 Google 的 OpenAPI 规范扩展程序,用于配置网关的行为。本页介绍了 OpenAPI 规范 2.0 的自定义 Google 特定扩展程序,这些扩展程序用于配置 API Gateway 行为,例如后端路由、身份验证和 API 管理功能。
虽然给出的示例采用的是 YAML 格式,但 JSON 也受支持。
命名惯例
Google OpenAPI 扩展程序的名称以 x-google- 前缀开头。
x-google-allow
x-google-allow: [configured | all]
此扩展程序在 OpenAPI 规范的顶层使用,用于指示应允许哪些网址路径通过 API Gateway。
可能的值有 configured 和 all。
默认值为 configured,这意味着只有您在 OpenAPI 规范中列出的 API 方法才能通过 API Gateway 提供服务。
使用 all 时,未配置的调用(无论是否包含 API 密钥或用户身份验证)都会通过 API Gateway 传递到您的 API。
API Gateway 会以区分大小写的方式处理对 API 的调用。例如,API Gateway 会将 /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,因此 API Gateway 会阻止以下请求,因为该请求没有 API 密钥:
https://my-project-id.appspot.com/widgets
由于 OpenAPI 规范中未列出 Widgets,因此 API Gateway 会将以下请求传递给您的服务,而无需 API 密钥:
https://my-project-id.appspot.com/Widgets/
如果 API 使用区分大小写的路由(并且您未将对“Widgets”的调用路由到任何代码),则 API 后端将返回 404。不过,如果您使用不区分大小写的路由,则 API 后端会将此调用路由到“widgets”。
不同的语言和框架采用不同的方法来控制大小写区分和路由。如需了解详情,请参阅框架的相关文档。
x-google-backend
x-google-backend 扩展程序指定了如何将请求路由到远程后端。扩展程序可以在 OpenAPI 规范的顶级、操作级或这两个级别指定。
x-google-backend 扩展程序还可以为远程后端配置其他设置,例如身份验证和超时。所有这些配置都可以按照每项操作的方式应用。
x-google-backend 扩展程序包含以下字段:
address
address: URL
必需。目标后端的网址。
该网址所用架构必须是 http 或 https。
路由到远程后端(无服务器)时,应设置此网址,其架构部分应为 https。
jwt_audience | disable_auth
这两项属性只能设置其中一项。
如果某项操作使用 x-google-backend 但未指定 jwt_audience 或 disable_auth,API Gateway 会自动将 jwt_audience 默认设置为与 address 匹配。如果未设置 address,API 网关会自动将 disable_auth 设置为 true。
jwt_audience
jwt_audience: string
可选。API Gateway 获取实例 ID 令牌时指定的 JWT 受众群体,随后在发出目标后端请求时使用。
为无服务器配置 API Gateway 时,应保护远程后端,使其仅允许来自 API Gateway 的流量。在代理请求时,API Gateway 会将实例 ID 令牌附加到 Authorization 标头。实例 ID 令牌表示用于部署 API Gateway 的运行时服务账号。然后,远程后端可以根据此附加令牌验证请求是否来自 API 网关。
例如,部署在 Cloud Run 上的远程后端可以使用 Identity and Access Management (IAM) 来执行以下操作:
- 通过撤消特殊
allUsers主账号中的roles/run.invoker来限制未经身份验证的调用。 - 通过向 API Gateway 运行时服务账号授予
roles/run.invoker角色,仅允许 API Gateway 调用后端。
默认情况下,API Gateway 将创建实例 ID 令牌,其 JWT 受众群体与 address 字段匹配。仅当目标后端使用基于 JWT 的身份验证且预期目标与 address 字段中指定的值不同时,才需要手动指定 jwt_audience。对于部署在 App Engine 上或使用 Identity-Aware Proxy (IAP) 的远程后端,您必须替换 JWT 受众群体。App Engine 和 IAP 使用其 OAuth 客户端 ID 作为预期目标对象。
启用此功能后,API Gateway 将更改请求中的标头。如果请求已设置 Authorization 标头,API 网关将:
- 将原始值复制到新标头
X-Forwarded-Authorization。 - 将
Authorization标头替换为实例 ID 令牌。
因此,如果 API 客户端设置了 Authorization 标头,则在 API Gateway 后面运行的后端应使用 X-Forwarded-Authorization 标头来检索整个 JWT。后端必须验证此标头中的 JWT,因为在未配置身份验证方法时,API Gateway 不会执行验证。
如需查看配置示例,请参阅创建 API 配置。
disable_auth
disable_auth: bool
可选。此属性用于确定 API Gateway 是否应阻止获取实例 ID 令牌并阻止将其附加到请求。
在配置目标后端时,如果符合以下任一条件,您可能不想使用 IAP 或 IAM 来对来自 API Gateway 的请求进行身份验证:
- 后端应允许未经身份验证的调用。
- 后端需要 API 客户端的原始
Authorization标头,并且不能使用X-Forwarded-Authorization(如jwt_audience部分所述)。
在这种情况下,请将此字段设为 true。
path_translation
path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]
可选。设置 API Gateway 在将请求代理到目标后端时使用的路径转换策略。
如需详细了解路径转换,请参阅了解路径转换部分。
当 x-google-backend 用于 OpenAPI 规范的顶层时,path_translation 默认为 APPEND_PATH_TO_ADDRESS;而当 x-google-backend 用于 OpenAPI 规范的操作级层时,path_translation 默认为 CONSTANT_ADDRESS。如果缺少 address 字段,path_translation 将保持未指定状态,并且不会发生。
deadline
deadline: double
可选。等待请求完整响应的秒数。
如果响应时间超过配置的截止时间,则会超时。在 SSE 或分块传输端点上,截止时间仍会限制整个流的持续时间;而在 gRPC 或 WebSocket 端点上,截止时间会限制消息之间的间隔。如需了解适用于每种请求的超时时间,请参阅设置流截止时间。
默认截止期限为 15.0 秒。
系统不会接受非正值。在这种情况下,API 网关会自动使用默认值。
最长可将时限配置为 3600 秒。非流式网关会强制执行较低的上限(即 600 秒),并在创建或更新网关时拒绝更高的截止时间,而不是在创建 API 配置时拒绝。
protocol
protocol: [ http/1.1 | h2 ]
可选。用于向后端发送请求的协议。
支持的值为 http/1.1 和 h2。
HTTP 和 HTTPS 后端的默认值为 http/1.1。
对于支持 HTTP/2 的安全 HTTP 后端 (https://),请将此字段设置为 h2 以提升性能。对于 Google Cloud 无服务器后端,建议使用此选项。
协议要求取决于流式传输类型:
- gRPC:您必须将协议设置为
h2。 - WebSockets:您必须使用
http/1.1。 - 服务器发送的事件 (SSE) 和增量响应交付:您可以使用
http/1.1或h2。我们建议使用h2以提升性能。
了解路径转换
当 API Gateway 处理请求时,它会获取原始请求路径,并在向目标后端发出请求之前对其进行转换。至于这种转换具体是如何发生的,则取决于您所使用的路径转换策略。有两种路径转换策略:
APPEND_PATH_TO_ADDRESS:将原始请求路径附加到x-google-backend扩展程序的address网址,借此计算目标后端请求路径。CONSTANT_ADDRESS:目标请求路径是常量,由x-google-backend扩展程序的address网址定义。如果相应的 OpenAPI 路径包含参数,则参数名称及其值会变为查询参数。
示例:
APPEND_PATH_TO_ADDRESSaddress: 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_ADDRESSaddress: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 扩展程序的用法。
配置 API Gateway 以允许 CORS 请求
如果从不同来源的网页应用调用您的 API,您的 API 必须支持跨源资源共享 (CORS)。如需了解如何配置 API Gateway 以支持 CORS,请参阅向 API Gateway 添加 CORS 支持。
如果您需要在后端代码中实现自定义 CORS 支持,请设置 allowCors: True,以便 API Gateway 将所有 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 令牌的签名。
x-google-jwks_uri (OpenAPI 2.0) 或 jwksUri (OpenAPI 3.x) 字段是必需的。
API Gateway 支持此 OpenAPI 扩展程序定义的两种非对称公钥格式:
-
JWK 集格式。
例如:
OpenAPI 2.0
x-google-jwks_uri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
OpenAPI 3.x
jwksUri: "https://YOUR_ACCOUNT_NAME.YOUR_AUTH_PROVIDER_URL/.well-known/jwks.json"
-
X509。例如:
OpenAPI 2.0
x-google-jwks_uri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
OpenAPI 3.x
jwksUri: "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
如果您使用的是对称密钥格式,请将 x-google-jwks_uri (OpenAPI 2.0) 或 jwksUri (OpenAPI 3.x) 设置为包含 base64url 编码的密钥字符串的文件的 URI。
x-google-jwt-locations
默认情况下,JWT 在 Authorization 标头(以 "Bearer " 为前缀)、X-Goog-Iap-Jwt-Assertion 标头或 access_token 查询参数中传递。
或者,您也可以使用 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 身份验证期间 JWT aud 字段应匹配的受众群体列表。此扩展服务接受一个字符串,其中包含以英文逗号分隔的值。不允许在受众群体之间添加空格。如果未指定,JWT aud 字段应与 OpenAPI 文档中的 host 字段一致。
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 > 服务页面上配额标签页中显示的用于标识指标的文本。您的 API 使用方还会在 IAM 和管理与 API 和服务下的配额页面上看到此文本。显示名称最多可以包含 40 个字符。 为了便于阅读,关联的配额限制的单位会自动附加到Google Cloud 控制台中的显示名称。例如,如果您将显示名称指定为“读取请求”,则Google Cloud 控制台中会显示“每个项目每分钟的读取请求数”。如果未指定,您的 API 的使用者会在 IAM 和管理以及 API 和服务下的配额页面上看到“未标记的配额”。 为了与 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}”,这意味着限额是按项目强制执行的,并且使用量每分钟都会重置。 |
| 值 | 必需。指标的限制。您必须将其指定为键值对,格式如下: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 的名称与 API Gateway 服务名称相同。(API Gateway 会使用您在 OpenAPI 文档的 host 字段中指定的名称作为服务的名称。)如果您的服务包含多个 API,那么您需要向 OpenAPI 文档添加 x-google-api-name 扩展程序,以指定 API 名称。借助 x-google-api-name 扩展程序,您可以明确命名各个 API,并为每个 API 建立独立的版本控制。
例如,您可以配置一个名为 api.example.com 的服务,其中包含两个 API:producer 和 consumer,并使用以下 OpenAPI 文档片段:
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 api-gateway api-configs create API_CONFIG_ID \ --api=my-api \ --openapi-spec="producer.yaml,consumer.yaml" \ --project=my-project-id