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 等網頁應用程式架構中包含啟用或停用區分大小寫轉送功能的設定選項。預設行為視您使用的架構而定。建議您查看架構中的設定,以確定啟用區分大小寫轉送功能。這項建議與以下 OpenAPI 規格 v2.0 規範一致:「規格中的所有欄位名稱都必須區分大小寫」。

範例

假設:

  • x-google-allow 設為 all。
  • OpenAPI 規格中列出的 API 方法是 widgets,而非 Widgets。
  • 您已將 OpenAPI 規格設為必須使用 API 金鑰。

由於 widgets 列在 OpenAPI 規格中,API Gateway 會封鎖下列要求,因為該要求沒有 API 金鑰:

https://my-project-id.appspot.com/widgets

由於 Widgets 未列在 OpenAPI 規格中,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 Gateway 會自動將 disable_auth 設為 true。

jwt_audience

jwt_audience: string

選用。API Gateway 取得執行個體 ID 權杖時指定的 JWT 目標對象,隨後會在提出目標後端要求時使用。

為無伺服器設定 API Gateway 時,應保護遠端後端,僅允許來自 API Gateway 的流量。API Gateway 會在轉送要求時,將執行個體 ID 權杖附加至 Authorization 標頭。執行個體 ID 權杖代表用於部署 API Gateway 的執行階段服務帳戶。遠端後端可以根據這個附加的權杖,驗證要求是否來自 API Gateway。

舉例來說,部署在 Cloud Run 的遠端後端可以使用 Identity and Access Management (IAM) 執行下列操作:

  1. 從特殊 allUsers 主體撤銷 roles/run.invoker,限制未經驗證的叫用。
  2. 將 roles/run.invoker 角色授予 API Gateway 執行階段服務帳戶,僅允許 API Gateway 叫用後端。

根據預設,API Gateway 會建立執行個體 ID 權杖,並使用與 address 欄位相符的 JWT 目標對象。只有在目標後端使用 JWT 驗證,且預期目標對象與 address 欄位中指定的值不同時,才需要手動指定 jwt_audience。如果遠端後端部署在 App Engine 上,或使用 Identity-Aware Proxy (IAP),則必須覆寫 JWT 目標對象。App Engine 和 IAP 會使用其 OAuth 用戶端 ID 做為預期目標對象。

啟用這項功能後,API Gateway 會變更要求中的標頭。如果要求已設定 Authorization 標頭,API Gateway 會:

  1. 將原始值複製到新標頭 X-Forwarded-Authorization。
  2. 使用執行個體 ID 權杖覆寫 Authorization 標頭。

因此,如果 API 用戶端設定 Authorization 標頭,在 API Gateway 後方執行的後端應使用 X-Forwarded-Authorization 標頭擷取整個 JWT。後端必須驗證這個標頭中的 JWT,因為未設定驗證方式時,API Gateway 不會執行驗證。

如需設定範例,請參閱「建立 API 設定」。

disable_auth

disable_auth: bool

選用。這項屬性決定 API Gateway 是否應禁止取得執行個體 ID 權杖,並禁止將其附加至要求。

設定目標後端時,如果符合下列任一條件,您可能不希望使用 IAP 或 IAM 驗證來自 API Gateway 的要求:

  1. 後端應允許未經驗證的叫用。
  2. 後端需要 API 用戶端的原始 Authorization 標頭,且無法使用 X-Forwarded-Authorization (如「jwt_audience」一節所述)。

在這種情況下,請將這個欄位設為 true。

path_translation

path_translation: [ APPEND_PATH_TO_ADDRESS | CONSTANT_ADDRESS ]

選用。設定 API Gateway 將要求轉送至目標後端時,使用的路徑轉譯策略。

如要進一步瞭解路徑轉譯,請參閱「瞭解路徑轉譯」一節。

在 OpenAPI 規格的頂層使用 x-google-backend 時,path_translation 預設為 APPEND_PATH_TO_ADDRESS;在 OpenAPI 規格的作業層級使用 x-google-backend 時,path_translation 預設為 CONSTANT_ADDRESS。如果缺少 address 欄位,path_translation 將維持未指定狀態,且不會發生。

deadline

deadline: double

選用。等待要求完整回應的秒數。如果回應時間超過設定的期限,就會逾時。在 SSE 或分塊傳輸端點上,期限仍會限制整個串流的時間長度;在 gRPC 或 WebSocket 端點上,期限則會限制訊息之間的間隔。如要瞭解各類要求的逾時時間,請參閱「設定串流期限」。預設期限為 15.0 秒。

如要使用預設值,請省略這個欄位或設為 0。負值也會使用預設值,但已淘汰:建立 API 設定時,如果使用負值,作業中繼資料會傳回警告,且日後版本會拒絕這類設定。

期限最長可設為 3600 秒。非串流閘道會強制執行較低的 600 秒上限,在建立或更新閘道時拒絕較高的期限,而不是在建立 API 設定時拒絕。

protocol

protocol: [ http/1.1 | h2 ]

選用。向後端傳送要求時使用的通訊協定。支援的值為 http/1.1 和 h2。

HTTP 和 HTTPS 後端的預設值為 http/1.1。

如果安全 HTTP 後端 (https://) 支援 HTTP/2,請將這個欄位設為 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_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 路徑:/hello
      • 要求路徑:/hello
      • 目標要求網址:https://my-project-id.appspot.com/BASE_PATH/hello
  • 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 路徑:/hello
      • 要求路徑:/hello
      • 目標要求網址:https://us-central1-my-project-id.cloudfunctions.net/helloGET

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 Token 的簽章。

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) 設為檔案的 URI,該檔案包含以 base64url 編碼的金鑰字串。

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 擴充功能中明確列出。舉例來說,如要僅支援 Authorization 標頭和 "Bearer " 前置字元,請使用下列程式碼:

  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 欄位一致。

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」(服務) 頁面中,「Quotas」(配額) 分頁上用來識別指標的顯示文字。這段文字也會顯示在「IAM & admin」(IAM 與管理) 和「APIs & Services」(API 和服務) 下方的「Quotas」(配額) 頁面,供 API 使用者查看。顯示名稱長度上限為 40 個字元。

為方便閱讀,Google Cloud 控制台會自動將相關配額限制的單位附加到顯示名稱。舉例來說,如果您將顯示名稱指定為「Read requests」,Google Cloud 控制台就會顯示「Read requests per minute per project」。如未指定,API 使用者會在「IAM & admin」(IAM 與管理) 和「APIs & Services」(API 與服務) 下方的「Quotas」(配額) 頁面中看到「unlabeled quota」(未加上標籤的配額)。

為與「Quotas」(配額) 頁面上列出的 Google 服務顯示名稱保持一致,建議您為顯示名稱採用下列做法:

  • 當您只有一個指標時,請使用「要求數」。
  • 如果您同時使用多項指標,則每個指標名稱都應說明要求類型,並含有「要求數」一詞,例如「讀取要求數」或「寫入要求數」。
  • 如有任何與指標相關聯的費用大於 1,請使用「配額單位」,而不要使用「要求數」。
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。
  • "YOUR-METRIC-NAME"::"YOUR-METRIC-NAME" 的文字必須與已定義的指標名稱相符。
  • METRIC-COST: 定義各項要求費用的整數值。要求提出之後,相關聯的指標會按照指定的費用遞增。在同一項指標中,費用可讓方法以不同的速率使用配額。舉例來說,如果某項指標的配額限制是 1,000、費用為 1,則在超過限制之前,呼叫端應用程式每分鐘可以提出 1,000 次要求。如果同一項指標的費用為 2,則在超過限制之前,呼叫端應用程式每分鐘只能提出 500 次要求。

配額範例

以下範例顯示如何為讀取要求和寫入要求新增指標與限制。

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,您可以將 x-google-api-name 擴充功能新增至 OpenAPI 文件,藉此指定各個 API 的名稱。x-google-api-name 擴充功能可讓您明確命名個別 API,並為每個 API 建立獨立版本。

舉例來說,您可以設定名為 api.example.com 的服務,其中包含 producer 和 consumer 兩個 API,並使用此處顯示的 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