

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# API Gateway WebSocket API
<a name="apigateway-websocket-api"></a>

API Gateway 中的 WebSocket API 是與後端 HTTP 端點、Lambda 函數或其他 AWS 服務整合的 WebSocket 路由集合。您可以使用 API Gateway 功能來協助您處理 API 生命週期的各個層面，從建立到監控生產 API。

API Gateway WebSocket API 是雙向的。用戶端可以將訊息傳送至服務，而且服務可以獨立地將訊息傳送給用戶端。這種雙向行為可提供更豐富的用戶端/服務互動，因為服務可以將資料推送至用戶端，而不需要用戶端提出明確請求。WebSocket 經常用於聊天應用程式、協作平台、多玩家遊戲和金融平台等即時應用程式。

如需開始使用的應用程式範例，請參閱 [教學：使用 WebSocket API、Lambda 和 DynamoDB 建立 WebSocket 聊天應用程式](websocket-api-chat-app.md)。

在本節中，您可以學習如何開發、發布、保護以及使用 API Gateway 監控您的 WebSocket API。

**Topics**
+ [API Gateway 中的 WebSocket API 概觀](apigateway-websocket-api-overview.md)
+ [在 API Gateway 中開發的 WebSocket API](websocket-api-develop.md)
+ [發布 WebSocket API 以供客戶調用](websocket-api-publish.md)
+ [在 API Gateway 中保護您的 WebSocket API](websocket-api-protect.md)
+ [在 API Gateway 中監控的 WebSocket API](websocket-api-monitor.md)

# API Gateway 中的 WebSocket API 概觀
<a name="apigateway-websocket-api-overview"></a>

在 API Gateway 中，您可以建立 WebSocket API 做為 AWS 服務 （例如 Lambda 或 DynamoDB) 或 HTTP 端點的狀態前端。WebSocket API 會根據自用戶端應用程式接收的訊息內容來後端。

WebSocket API 與 REST API 不同 (其會接收並回應請求)，會支援用戶端應用程式和後端之間的雙向通訊。該後端可以將回呼訊息傳送到連線用戶端。

在 WebSocket API 中，是根據您設定的路由將傳入 JSON 訊息導向到後端整合。(會將非 JSON 訊息導向您設定的 `$default` 路由。)

*路由*包含的*路由金鑰*，是您可以在*路由選擇表達式*經評估後即預期的值。`routeSelectionExpression` 是在 API 層級定義的屬性。它指定的 JSON 屬性預計會出現在訊息承載。如需路由選擇表達式的詳細資訊，請參閱[路由選擇表達式](websocket-api-develop-routes.md#apigateway-websocket-api-route-selection-expressions)。

例如，如果您的 JSON 訊息包含 `action` 屬性，以及您想要根據此屬性執行不同動作，路由選擇表達式可能會 `${request.body.action}`。您的路由表將指定要執行哪一個動作，方法是將 `action` 屬性值與您在資料表中定義的自訂路由鍵值進行比對。

## 使用 WebSocket API 的路由
<a name="apigateway-websocket-api-overview-routes"></a>

有三種預先定義的路由可供使用：`$connect`、`$disconnect` 和 `$default`。此外，您可以建立自訂路由。
+ API Gateway 會在用戶端和 WebSocket API 之間的持續連線進行起始化時呼叫 `$connect` 路由。
+ 當用戶端或伺服器中斷與 API 的連線時，API Gateway 會呼叫 `$disconnect` 路由。
+ 若發現相符的路由，針對該訊息評估路由選擇運算式後，API Gateway 即會呼叫自訂路由；該比對會判斷要叫用哪些整合。
+ 如果未發現相符路由，或無法針對該訊息來評估路由選擇表達式時，API Gateway 會呼叫 `$default` 路由。

如需 `$connect` 和 `$disconnect` 路由的相關資訊，請參閱[管理連線的使用者和用戶端應用程式：`$connect` 和 `$disconnect` 路由](apigateway-websocket-api-route-keys-connect-disconnect.md)。

如需 `$default` 路由和自訂路由的相關資訊，請參閱[在 API Gateway 中調用與 `$default` Route 和自訂路由的後端整合](apigateway-websocket-api-routes-integrations.md)。

## 將資料傳送至連線的用戶端應用程式
<a name="apigateway-websocket-api-overview-send-data"></a>

後端服務可將資料傳送到連線的用戶端應用程式。您可以藉由執行以下動作來傳送電子郵件：
+ 使用整合以傳送回應，該回應會由您已定義的路由傳回到用戶端。
+ 您可以使用 `@connections` API 來傳送 POST 請求。如需詳細資訊，請參閱[在後端服務使用 `@connections` 命令](apigateway-how-to-call-websocket-api-connections.md)。

## WebSocket API 狀態碼
<a name="apigateway-websocket-status-codes"></a>

API Gateway WebSocket API 使用以下狀態碼作為從伺服器到用戶端的通訊方式，如 [WebSocket 關閉代碼編號登錄檔](https://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number)中所述：

1001  
當用戶端閒置 10 分鐘或達到最長 2 小時連線生命週期時，API Gateway 會傳回此狀態碼。

1003  
當端點收到二進位媒體類型時，API Gateway 會傳回此狀態碼。WebSocket API 不支援二進位媒體類型。

1005  
如果用戶端傳送的關閉框架沒有關閉碼，API Gateway 就會傳回此狀態碼。

1006  
如果連線意外關閉，例如，TCP 連線在沒有 WebSocket 關閉框架的情況下關閉，API Gateway 就會傳回此狀態碼。

1008  
當端點收到來自特定用戶端的過多請求時，API Gateway 會傳回此狀態碼。

1009  
當端點收到的訊息太大而無法處理時，API Gateway 會傳回此狀態碼。

1011  
發生內部伺服器錯誤時，API Gateway 會傳回此狀態碼。

1012  
如果服務重新啟動，API Gateway 會傳回此狀態碼。

# 管理連線的使用者和用戶端應用程式：`$connect` 和 `$disconnect` 路由
<a name="apigateway-websocket-api-route-keys-connect-disconnect"></a>

下一節說明如何使用 WebSocket API 的 `$connect` 和 `$disconnect` 路由。

**Topics**
+ [`$connect` 路由](#apigateway-websocket-api-routes-about-connect)
+ [從 `$connect` 路由傳遞連線資訊](#apigateway-websocket-api-passing-connectionId-on-connect)
+ [`$disconnect` 路由](#apigateway-websocket-api-routes-about-disconnect)

## `$connect` 路由
<a name="apigateway-websocket-api-routes-about-connect"></a>

用戶端應用程式會透過傳送 WebSocket 升級請求來連線到 WebSocket API。如果請求成功，會在建立連線的同時執行 `$connect` 路由。

由於 WebSocket 連線是狀態連接，您可以僅對 `$connect` 路由設定授權。`AuthN`/`AuthZ` 將只會在連線時執行。

在與 `$connect` 路由關聯的整合執行完成後，升級請求會處於等待中，且將不會建立實際的連線。如果 `$connect` 請求失敗 (例如，由於 `AuthN`/`AuthZ` 故障或整合故障)，將不會進行連線。

**注意**  
如果在進行 `$connect` 時授權失敗，就不會建立連線，用戶端將會收到 `401` 或 `403` 回應。

為 `$connect` 設定整合是選用的。您應在以下情況考慮設定 `$connect` 整合：
+ 您想要讓用戶端使用 `Sec-WebSocket-Protocol` 欄位來指定子通訊協定。如需範例程式碼，請參閱[設定需要 WebSocket 子協定的 `$connect` 路由](websocket-connect-route-subprotocol.md)。
+ 您希望在用戶端連線時收到通知。
+ 您想要調節連線或控制連線的人員。
+ 您想要後端使用回呼 URL 將訊息傳回給用戶端。
+ 您想將每個連線 ID 和其他資訊放到資料庫 (例如，Amazon DynamoDB)。

## 從 `$connect` 路由傳遞連線資訊
<a name="apigateway-websocket-api-passing-connectionId-on-connect"></a>

 您可以同時使用代理和非代理整合，將資訊從 `$connect` 路由傳遞至資料庫或其他 AWS 服務。

### 使用代理整合傳遞連線資訊
<a name="websocket-connect-proxy-integration"></a>

您可以從事件中的 Lambda 代理整合存取連線資訊。使用另一個 AWS 服務 或 AWS Lambda 函數來發佈至連線。

下列 Lambda 函數顯示如何使用 `requestContext` 物件來記錄連線 ID、網域名稱、階段名稱和查詢字串。

------
#### [ Node.js ]

```
 export const handler = async(event, context) => {
    const connectId = event["requestContext"]["connectionId"]
    const domainName = event["requestContext"]["domainName"]
    const stageName = event["requestContext"]["stage"]
    const qs = event['queryStringParameters']
    console.log('Connection ID: ', connectId, 'Domain Name: ', domainName, 'Stage Name: ', stageName, 'Query Strings: ', qs )
    return {"statusCode" : 200}
};
```

------
#### [ Python ]

```
import json
import logging
logger = logging.getLogger()
logger.setLevel("INFO")


def lambda_handler(event, context):
    connectId = event["requestContext"]["connectionId"]
    domainName = event["requestContext"]["domainName"]
    stageName = event["requestContext"]["stage"]
    qs = event['queryStringParameters']
    connectionInfo = {
        'Connection ID': connectId,
        'Domain Name': domainName,
        'Stage Name': stageName,
        'Query Strings': qs}
    logging.info(connectionInfo)
    return {"statusCode": 200}
```

------

### 使用非代理整合傳遞連線資訊
<a name="websocket-connect-non-proxy-integration"></a>
+ 您可以透過非代理整合存取連線資訊。設定整合要求並提供 WebSocket API 要求範本。下列 [Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 對應範本以提供整合要求。此要求會將下列詳細資訊傳送至非 Proxy 整合：
  + 連線 ID
  + 網域名稱
  + 階段名稱
  + 路徑
  + 標頭
  + 查詢字串

  此要求會將連線 ID、網域名稱、階段名稱、路徑、標頭和查詢字串傳送至非 Proxy 整合。

  ```
  {
      "connectionId": "$context.connectionId",
      "domain": "$context.domainName",
      "stage": "$context.stage",
      "params": "$input.params()"
  }
  ```

  如需設定資料轉換的詳細資訊，請參閱 [API Gateway 中用於 WebSocket API 的資料轉換](websocket-api-data-transformations.md)。

  如要完成整合請求，請設定整合回應的 `StatusCode: 200`。若要深入瞭解如何設定整合回應，請參閱 [使用 API Gateway 主控台設定整合回應](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-using-console)。

## `$disconnect` 路由
<a name="apigateway-websocket-api-routes-about-disconnect"></a>

`$disconnect` 路由會在連線關閉後執行。

連線可以由伺服器或用戶端關閉。由於連接在執行時已經關閉，`$disconnect` 是一個最佳努力的事件。API Gateway 會盡力將 `$disconnect` 事件傳遞給整合，但無法保證傳遞成功。

後端可以透過使用 `@connections` API 來起使化中斷連線。如需詳細資訊，請參閱[在後端服務使用 `@connections` 命令](apigateway-how-to-call-websocket-api-connections.md)。

# 在 API Gateway 中調用與 `$default` Route 和自訂路由的後端整合
<a name="apigateway-websocket-api-routes-integrations"></a>

下一節說明如何使用 WebSocket API 的`$default` 路由或自訂路由來調用您的後端整合。

**Topics**
+ [使用路由來處理訊息](#apigateway-websocket-api-overview-routes)
+ [`$default` 路由](#apigateway-websocket-api-routes-about-default)
+ [自訂路由](#apigateway-websocket-api-routes-about-custom)
+ [使用 API Gateway WebSocket API 整合，以連接到商業邏輯](#apigateway-websocket-api-overview-integrations)
+ [WebSocket API 和 REST API 之間的重要差異](#apigateway-websocket-api-overview-integrations-differences)

## 使用路由來處理訊息
<a name="apigateway-websocket-api-overview-routes"></a>

在 API Gateway WebSocket API 中，您可以將訊息從用戶端傳送到後端服務，反之亦然。後端與在 WebSocket 中的 HTTP 請求/回應模型不同，可以將訊息傳送給用戶端，而用戶端不需採取任何動作。

訊息可以是 JSON 或非 JSON。不過，只能夠根據訊息內容將 JSON 訊息路由到特定的整合。會透過 `$default` 路由將非 JSON 訊息傳遞到後端。

**注意**  
API Gateway 將支援高達 128 KB 的訊息承載，影格大小上限為 32 KB。如果訊息超過 32 KB，則必須分割成多個影格，每個為 32 KB 或以下。如果接收到更大的訊息 (或影格)，則該連線會關閉，並出現程式碼 1009。  
目前不支援二進位承載。如果接收到二進位影格，則該連線會關閉，並出現程式碼 1003。不過，您可以將二進位承載轉換為文字。請參閱[API Gateway 中 WebSocket API 的二進位媒體類型](websocket-api-develop-binary-media-types.md)。

可透過 API Gateway 中的 WebSocket API，將 JSON 訊息路由以根據訊息內容執行特定的後端服務。當用戶端透過其 WebSocket 連線傳送訊息後，此會造成對 WebSocket API 發出*路由請求*。會透過 API Gateway 中之對應的路由金鑰來將請求對應至路由。您可以使用 AWS CLI或使用 AWS SDK，在 API Gateway 主控台中設定 WebSocket API 的路由請求。

**注意**  
在 AWS CLI AWS SDKs中，您可以在建立整合之前或之後建立路由。目前主控台不支援整合的重複使用，因此您必須先建立路由，然後建立該路由的整合。

您可以將 API Gateway 設定為對路由執行驗證，再繼續進行整合請求。如果驗證失敗，API Gateway 失敗請求，而不呼叫後端，傳送與以下用戶端類似的 `"Bad request body"` 閘道回應，以及在 CloudWatch Logs 中發布驗證結果：

```
{"message" : "Bad request body", "connectionId": "{connectionId}", "messageId": "{messageId}"}
```

這可減少對後端不必要的呼叫，讓您專注在 API 的其他要求。

您也可以為 API 路由定義路由回應，以啟用雙向通訊。路由回應說明會在特定路由整合完成時，將哪些資料傳送到用戶端。例如，如果您希望用戶端將訊息傳送到後端，而不接收回應 (單向通訊)，您不需要定義路由的回應。不過，如果您不提供路由回應，API Gateway 不會將任何與您整合結果相關的資訊傳送到用戶端。

## `$default` 路由
<a name="apigateway-websocket-api-routes-about-default"></a>

每個 API Gateway WebSocket API 都可以具備 `$default` 路由。這是一個特殊路由值，使用方式如下：
+ 您可以使用該值搭配定義的路由金鑰，來為不符合任何定義路由金鑰的內送訊息指定「備用」路由 (例如，一般偽裝整合，會傳回特定的錯誤訊息)。
+ 您可以使用該值與任何定義路由金鑰，來指定將路由委派到後端元件的 Proxy 模型。
+ 您可以使用該值來為非 JSON 承載指定路由。

## 自訂路由
<a name="apigateway-websocket-api-routes-about-custom"></a>

如果您想要根據訊息內容來叫用特定的整合，則可透過建立自訂路由來這麼做。

自訂路由會使用您指定的路由金鑰和整合。當內送訊息包含 JSON 屬性，而且該屬性的判斷值符合路由金鑰值時，API Gateway 會叫用整合。(如需詳細資訊，請參閱「[API Gateway 中的 WebSocket API 概觀](apigateway-websocket-api-overview.md)」。)

例如，假設您想要建立聊天空間應用程式。您可以透過建立路由選擇表達式為 `$request.body.action` 的 WebSocket API 來開始。然後，您可以接著定義兩個路由：`joinroom` 和 `sendmessage`。用戶端應用程式可以透過傳送如下訊息，來叫用 `joinroom` 路由：

```
{"action":"joinroom","roomname":"developers"}
```

其可以透過傳送如下訊息，來叫用 `sendmessage` 路由：

```
{"action":"sendmessage","message":"Hello everyone"}
```

## 使用 API Gateway WebSocket API 整合，以連接到商業邏輯
<a name="apigateway-websocket-api-overview-integrations"></a>

在為 API Gateway WebSocket API 設定路由後，您必須指定您想使用的整合。如同路由 (可能會擁有路由請求和路由回應)，整合可以擁有*整合請求*和*整合回應*。*整合請求*包含後端預期的資訊，以處理來自您用戶端的請求。*整合回應*包含後端傳回到 API Gateway 的資料，而且可能會用於建構訊息以傳送到用戶端 (如果路由回應已定義)。

如需設定整合的詳細資訊，請參閱[API Gateway 中 WebSocket API 的整合](apigateway-websocket-api-integrations.md)。

## WebSocket API 和 REST API 之間的重要差異
<a name="apigateway-websocket-api-overview-integrations-differences"></a>

WebSocket API 整合與 REST API 整合類似，但差異如下：
+ 目前，您必須先在 API Gateway 主控台中建立路由，然後建立整合做為該路由的目標。不過，您可以在 API 和 CLI 中，以任何順序單獨建立路由和整合。
+ 您可以為多個路由使用單一整合。例如，如果您有一組動作彼此間密切關聯，您可能需要所有路由來移至單一 Lambda 函數。您不必多次定義整合的詳細資訊，您可以指定一次，並將其指派給每個相關的路由。
**注意**  
目前主控台不支援整合的重複使用，因此您必須先建立路由，然後建立該路由的整合。  
在 AWS CLI 和 AWS SDKs中，您可以透過將路由的目標設定為 的值來重複使用整合`"integrations/{integration-id}"`，其中 `{integration-id}"`是與路由相關聯的整合的唯一 ID。
+ API Gateway 提供您可以在路由和整合使用的多種[選擇表達式](apigateway-websocket-api-selection-expressions.md)。您不需要倚賴內容類型來選取輸入範本或輸出映射。如同路由選擇表達式，您可以定義由 API Gateway 評估的選擇表達式來適當的項目。如果未找到相符範本，所有這些都會回復為 `$default` 範本。
  + 在整合請求中，範本選擇表達式支援 `$request.body.<json_path_expression>` 和靜態值。
  + 在整合回應中，範本選擇表達式支援 `$request.body.<json_path_expression>`、`$integration.response.statuscode`、`$integration.response.header.<headerName>` 和靜態值。

在 HTTP 通訊協定 (其中請求和回應會同步傳送) 中；通訊基本上是單向。在 WebSocket 協定中，通訊是雙向。回應是非同步的，用戶端收到的順序與用戶端訊息的傳送順序不一定相同。此外，後端可以將訊息給傳送用戶端。

**注意**  
對於設定為使用 `AWS_PROXY` 或 `LAMBDA_PROXY` 整合的路由，通訊是單向，API Gateway 不會自動將後端回應傳遞至路由回應。例如，在 `LAMBDA_PROXY` 整合的情況下，就不會將 Lambda 函數傳回的內文傳回給用戶端。如果您希望用戶端接收整合回應，您必須定義路由回應，以進行雙向的通訊。

# WebSocket 選擇表達式
<a name="apigateway-websocket-api-selection-expressions"></a>

API Gateway 使用選擇表達式來評估請求及回應內容並產生金鑰。然後，金鑰會用來選擇一組通常由您 (即 API 開發人員) 提供的可能值。所支援的實際變數組將取決於特定表達式，各表達式詳細說明如下。

所有表達式的語言都遵循同一組規則：
+ 變數字首會加上 `"$"`。
+ 大括號可用來明確定義變數邊界，例如 `"${request.body.version}-beta"`。
+ 支援多個變數，但僅會評估一次 (無遞迴評估)。
+ 貨幣符號 (`$`) 可用 `"\"` 逸出。在定義映射至預留 `$default` 金鑰 (如 `"\$default"`) 的表達式時，這條規則十分實用。
+ 有時需要模式格式，此時，表達式前後應以斜線 (`"/"`) 包裝，例如應符合 `"/2\d\d/"` 狀態碼的 `2XX`。

**Topics**
+ [路由回應選擇表達式](#apigateway-websocket-api-route-response-selection-expressions)
+ [API 金鑰選擇表達式](#apigateway-websocket-api-apikey-selection-expressions)
+ [API 映射選擇表達式](#apigateway-websocket-api-mapping-selection-expressions)
+ [WebSocket 選擇表達式總結](#apigateway-websocket-api-selection-expression-table)

## 路由回應選擇表達式
<a name="apigateway-websocket-api-route-response-selection-expressions"></a>

[路由回應](apigateway-websocket-api-route-response.md)係用來將後端到用戶端的回應建模。以 WebSocket API 而言，路由回應為選用。如有定義，將指示 API Gateway 在接收 WebSocket 訊息時應將回應回傳至用戶端。

*路由回應選擇表達式*的評估將產生路由回應金鑰。此金鑰最終將選擇其中一個與 API 相關聯的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html)。然而，目前僅支援 `$default` 金鑰。

## API 金鑰選擇表達式
<a name="apigateway-websocket-api-apikey-selection-expressions"></a>

本服務判定特定請求只在用戶端提供有效的 [API 金鑰](api-gateway-basic-concept.md#apigateway-definition-api-key)後才會繼續處理，此時將評估此表達式。

目前僅支援兩個值：`$request.header.x-api-key` 及 `$context.authorizer.usageIdentifierKey`。

## API 映射選擇表達式
<a name="apigateway-websocket-api-mapping-selection-expressions"></a>

當請求使用自訂網域提出時，須評估此表達式來判定應選取的 API 階段。

目前，僅支援的值為 `$request.basepath`。

## WebSocket 選擇表達式總結
<a name="apigateway-websocket-api-selection-expression-table"></a>

下表總結 WebSocket API 內選擇表達式的使用案例：


| 選擇表達式 | 判斷值為下列的金鑰 | 備註 | 範例使用案例 | 
| --- | --- | --- | --- | 
| Api.RouteSelectionExpression | Route.RouteKey | 所支援的 \$1default 為全部截獲路由。 | 依據用戶端請求內容路由 WebSocket 訊息。 | 
| Route.ModelSelectionExpression | Route.RequestModels 的金鑰 | 選用。 若提供給非代理整合，將出現模型驗證。 所支援的 `$default` 為全部截獲。  | 在相同路由內動態執行請求驗證。 | 
| Integration.TemplateSelectionExpression | Integration.RequestTemplates 的金鑰 |  選用。 可供非代理整合使用，藉此操控傳入承載。 支援 `${request.body.jsonPath}` 和靜態值。 所支援的 `$default` 為全部截獲。  | 依據請求的動態屬性操控發起人的請求。 | 
| Integration.IntegrationResponseSelectionExpression | IntegrationResponse.IntegrationResponseKey |  選用。可供非代理整合使用。 做為錯誤訊息 (來自 Lambda) 或狀態碼 (來自 HTTP 整合) 的模式比對。 非代理整合必須有 `$default` 來全部截獲成功回應。  |  從後端操控回應。 依據後端的動態回應來選擇欲採取的動作 (如明確處理特定錯誤)。  | 
| IntegrationResponse.TemplateSelectionExpression | IntegrationResponse.ResponseTemplates 的金鑰 | 選用。可供非代理整合使用。支援 \$1default。  |  回應的動態屬性有時會在相同路由與相關聯整合內做出不同轉換的決定。 支援 `${request.body.jsonPath}`、`${integration.response.statuscode}`、`${integration.response.header.headerName}`、`${integration.response.multivalueheader.headerName}` 和靜態值。 所支援的 `$default` 為全部截獲。  | 
| Route.RouteResponseSelectionExpression | RouteResponse.RouteResponseKey |  應提供，藉以啟動 WebSocket 路由的雙向通訊。 目前此值限制為 `$default`。  |  | 
| RouteResponse.ModelSelectionExpression | RouteResponse.RequestModels 的金鑰 | 目前不支援。 |  | 

# 在 API Gateway 中開發的 WebSocket API
<a name="websocket-api-develop"></a>

本節提供開發 API Gateway API 時所需的 API Gateway 功能的詳細資料。

在開發 API Gateway API 時，您可以決定 API 的許多特性。這些特性取決於 API 的使用案例。例如，您可能只允許特定用戶端呼叫您的 API，或是您可能希望讓所有人都可以使用它。您可能需要 API 呼叫來執行 Lambda 函數、進行資料庫查詢或呼叫應用程式。

**Topics**
+ [在 API Gateway 中建立 WebSocket API](apigateway-websocket-api-create-empty-api.md)
+ [API Gateway 中 WebSocket API 的 IP 位址類型](websocket-api-ip-address-type.md)
+ [在 API Gateway 中建立 WebSocket API 的路由](websocket-api-develop-routes.md)
+ [在 API Gateway 中控制和管理對 WebSocket API 的存取](apigateway-websocket-api-control-access.md)
+ [API Gateway 中 WebSocket API 的整合](apigateway-websocket-api-integrations.md)
+ [請求驗證 API Gateway 中的 WebSocket API](websocket-api-request-validation.md)
+ [API Gateway 中用於 WebSocket API 的資料轉換](websocket-api-data-transformations.md)
+ [API Gateway 中 WebSocket API 的二進位媒體類型](websocket-api-develop-binary-media-types.md)
+ [調用 WebSocket API](apigateway-how-to-call-websocket-api.md)

# 在 API Gateway 中建立 WebSocket API
<a name="apigateway-websocket-api-create-empty-api"></a>

您可以在 API Gateway 主控台中使用 [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 命令， AWS CLI 或在 AWS SDK 中使用 `CreateApi` 命令來建立 WebSocket API。下列程序顯示如何建立新的 WebSocket API。

**注意**  
WebSocket API 僅支援 TLS 1.2 和 TLS 1.3。不支援舊版 TLS。

## 使用 AWS CLI 命令建立 WebSocket API
<a name="apigateway-websocket-api-create-using-awscli"></a>

以下 [create-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 命令會建立具有 `$request.body.action` 路由選擇表達式的 API：

```
aws apigatewayv2 --region us-east-1 create-api --name "myWebSocketApi3" --protocol-type WEBSOCKET --route-selection-expression '$request.body.action'
```

輸出看起來如下：

```
{
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "Name": "myWebSocketApi3",
    "CreatedDate": "2018-11-15T06:23:51Z",
    "ProtocolType": "WEBSOCKET",
    "RouteSelectionExpression": "'$request.body.action'",
    "ApiId": "aabbccddee"
}
```

## 使用 API Gateway 主控台建立 WebSocket API
<a name="apigateway-websocket-api-create-using-console"></a>

您可以選擇 WebSocket 通訊協定並為 API 提供名稱，以在主控台中建立 WebSocket API。

**重要**  
一旦建立 API 後，您無法更改您選擇的通訊協定。您無法將 WebSocket API 轉換到 REST API，反之亦然。

**使用 API Gateway 主控台建立 WebSocket API**

1. 登入 API Gateway 主控台，然後選擇 **Create API (建立 API)**。

1. 在 **WebSocket API** 下，選擇 **Build (建置)**。僅支援區域端點。

1. 針對 **API 名稱**，輸入您 API 的名稱。

1. 針對**路由選擇表達式**輸入值。例如 `$request.body.action`。

   如需路由選擇表達式的詳細資訊，請參閱[路由選擇表達式](websocket-api-develop-routes.md#apigateway-websocket-api-route-selection-expressions)。

1. 執行以下任意一項：
   + 選擇**建立空白 API** 以建立沒有路由的 API。
   + 選擇**下一步**將路由附加到您的 API。

   您可以在建立 API 之後附加路由。

# API Gateway 中 WebSocket API 的 IP 位址類型
<a name="websocket-api-ip-address-type"></a>

建立 API 時，您可以指定可調用 API 的 IP 位址類型。您可以選擇 IPv4 來解析 IPv4 位址以調用 API，也可以選擇雙堆疊，以同時允許 IPv4 和 IPv6 位址調用您的 API。我們建議您將 IP 位址類型設定為雙堆疊，以緩解 IP 空間耗盡或用於安全狀態。如需雙堆疊 IP 位址類型優點的詳細資訊，請參閱 [AWS 上的 IPv6](https://docs.aws.amazon.com/whitepapers/latest/ipv6-on-aws/internet-protocol-version-6.html)。

## IP 位址類型的考量事項
<a name="websocket-api-ip-address-type-considerations"></a>

下列考量事項可能會影響您使用 IP 位址類型：
+ 所有 WebSocket API 的預設 IP 位址類型都是 IPv4。
+ 如果您將現有 API 的 IP 位址類型從 IPv4 變更為雙堆疊，請確認控制存取 API 的任何政策都已更新，以便進行 IPv6 呼叫。當您變更 IP 位址類型時，變更會立即生效。
+ 您的 API 可以對應至與您的 API 具有不同 IP 位址類型的自訂網域名稱。如果您停用預設 API 端點，則可能會影響呼叫方調用 API 的方式。

## 變更 WebSocket API 的 IP 位址類型
<a name="websocket-api-ip-address-type-change"></a>

您可以藉由更新 API 的組態來變更 IP 位址類型。您可以使用 AWS 管理主控台、AWS CLI、CloudFormation 或 AWS SDK 來更新 API 的組態。如果您變更 API 的 IP 位址類型，您不需重新部署 API 讓變更生效。

------
#### [ AWS 管理主控台 ]

**若要變更 WebSocket API 的 IP 位址類型**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇 WebSocket API。

1. 選擇 **API 設定**，然後選擇**編輯**。

1. 針對 IP 位址類型，選取 **IPv4** 或**雙堆疊**。

1. 選擇**儲存**。

   對 API 組態的變更會立即生效。

------
#### [ AWS CLI ]

以下 [update-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-api.html) 命令會將 API 更新為雙堆疊 IP 位址類型：

```
aws apigatewayv2 update-api \
    --api-id abcd1234 \
    --ip-address-type dualstack
```

輸出將如下所示：

```
{
    "ApiEndpoint": "https://abcd1234.execute-api.us-east-1.amazonaws.com",
    "ApiId": "abcd1234",
    "ApiKeySelectionExpression": "$request.header.x-api-key",
    "CreatedDate": "2025-02-04T22:20:20+00:00",
    "DisableExecuteApiEndpoint": false,
    "Name": "My-WebSocket-API",
    "ProtocolType": "WEBSOCKET",
    "RouteSelectionExpression": "$request.method $request.path",
    "Tags": {},
    "NotificationUris": [],
    "IpAddressType": "dualstack"
}
```

------

# 在 API Gateway 中建立 WebSocket API 的路由
<a name="websocket-api-develop-routes"></a>

在 WebSocket API 中，是根據您設定的路由將傳入 JSON 訊息導向到後端整合。(會將非 JSON 訊息導向您設定的 `$default` 路由。)

*路由*包含的*路由金鑰*，是您可以在*路由選擇表達式*經評估後即預期的值。`routeSelectionExpression` 是在 API 層級定義的屬性。它指定的 JSON 屬性預計會出現在訊息承載。如需路由選擇表達式的詳細資訊，請參閱[路由選擇表達式](#apigateway-websocket-api-route-selection-expressions)。

例如，如果您的 JSON 訊息包含 `action` 屬性，以及您想要根據此屬性執行不同動作，路由選擇表達式可能會 `${request.body.action}`。您的路由表將指定要執行哪一個動作，方法是將 `action` 屬性值與您在資料表中定義的自訂路由鍵值進行比對。

有三種預先定義的路由可供使用：`$connect`、`$disconnect` 和 `$default`。此外，您可以建立自訂路由。
+ API Gateway 會在用戶端和 WebSocket API 之間的持續連線進行起始化時呼叫 `$connect` 路由。
+ 當用戶端或伺服器中斷與 API 的連線時，API Gateway 會呼叫 `$disconnect` 路由。
+ 若發現相符的路由，針對該訊息評估路由選擇運算式後，API Gateway 即會呼叫自訂路由；該比對會判斷要叫用哪些整合。
+ 如果未發現相符路由，或無法針對該訊息來評估路由選擇表達式時，API Gateway 會呼叫 `$default` 路由。

## 路由選擇表達式
<a name="apigateway-websocket-api-route-selection-expressions"></a>

本服務針對傳入訊息選擇欲遵循的路由時，將評估*路由選擇表達式*。本服務將使用 `routeKey` 與評估值完全相符的路由。若無相符路由，且某路由存在 `$default` 路由金鑰，將選取該路由。若沒有路由符合評估值，而且沒有 `$default` 路由，本服務將回傳錯誤。以 WebSocket 型的 API 而言，表達式的形式應為 `$request.body.{path_to_body_element}`。

例如，假設您正傳送下列 JSON 訊息：

```
{
    "service" : "chat",
    "action" : "join",
    "data" : {
        "room" : "room1234"
   }
}
```

您可能想要根據 `action` 屬性來選取您的 API 行為。此時，您可以定義下列路由選擇表達式：

```
$request.body.action
```

此範例中，`request.body` 係指您訊息的 JSON 承載，而 `.action` 則為 [JSONPath](https://goessner.net/articles/JsonPath/) 表達式。`request.body` 之後可使用任何 JSON 路徑表達式，但請記住結果會字串化。例如，若您的 JSONPath 表達式回傳兩個元素的陣列，該結果將以字串 `"[item1, item2]"` 呈現。有鑑於此，理想做法是將表達式的評估結果設為一個值，而非陣列或物件。

您可僅使用靜態值，或者也可以使用多個變數。下表為上述承載的範例及其評估結果。


| 表達式 | 評估結果 | 描述 | 
| --- | --- | --- | 
| \$1request.body.action | join | 未包裝的變數 | 
| \$1\$1request.body.action\$1 | join | 已包裝的變數 | 
| \$1\$1request.body.service\$1/\$1\$1request.body.action\$1 | chat/join | 具備靜態值的多個變數 | 
| \$1\$1request.body.action\$1-\$1\$1request.body.invalidPath\$1  | join- | 若未找到 JSONPath，則變數將解析為 ""。 | 
| action | action | 靜態值 | 
| \$1\$1default | \$1default | 靜態值 | 

評估結果將用於尋找路由。若某路由具備相符的路由金鑰，將選取該路由來處理訊息。若找不到相符的路由，則 API Gateway 會嘗試尋找 `$default` 路由 (如有)。若未定義 `$default` 路由，則 API Gateway 會傳回錯誤。

## 在 API Gateway 中設定 WebSocket API 的路由
<a name="apigateway-websocket-api-routes"></a>

首次新建的 WebSocket API 有三個預先定義的路由：`$connect`、`$disconnect` 和 `$default`，您可以使用 主控台、API 或 建立它們 AWS CLI。如有需要，您可以建立自訂路由。如需更多詳細資訊，請參閱 [API Gateway 中的 WebSocket API 概觀](apigateway-websocket-api-overview.md)。

**注意**  
在 CLI 中，您可在建立整合之前或之後建立路由，也可以在多個路由重複使用相同整合。

### 使用 API Gateway 主控台建立路由
<a name="apigateway-websocket-api-route-using-console"></a>

**使用 API Gateway 主控台建立路由**

1. 登入 API Gateway 主控台、選擇 API，然後選擇 **Routes (路由)**。

1. 選擇**建立路由**。

1. 針對**路由金鑰**，輸入路由金鑰名稱。您可以建立預先定義的路由 (`$connect`、`$disconnect` 和 `$default`)，或是自訂路由。
**注意**  
建立自訂路由時，請勿在路由金鑰名稱字首使用 `$`。此字首保留供預先定義路由使用。

1. 選取並設定路由的整合類型。如需詳細資訊，請參閱[使用 API Gateway 主控台設定 WebSocket API 整合請求](apigateway-websocket-api-integration-requests.md#apigateway-websocket-api-integration-request-using-console)。

### 使用 建立路由 AWS CLI
<a name="apigateway-websocket-api-route-using-awscli"></a>

以下 [create-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route.html) 命令會建立路由：

```
aws apigatewayv2 --region us-east-1 create-route --api-id aabbccddee --route-key $default
```

輸出將如下所示：

```
{
    "ApiKeyRequired": false,
    "AuthorizationType": "NONE",
    "RouteKey": "$default",
    "RouteId": "1122334"
}
```

### 指定 `$connect` 的路由請求設定
<a name="apigateway-websocket-api-route-request-connect"></a>

設定 API 的 `$connect` 路由時，可使用下列選用設定，以啟用您 API 的授權。如需更多詳細資訊，請參閱 [`$connect` 路由](apigateway-websocket-api-route-keys-connect-disconnect.md#apigateway-websocket-api-routes-about-connect)。
+ **Authorization (授權)**：若無須授權，可指定為 `NONE`。否則，您可指定：
  + `AWS_IAM` 使用標準 AWS IAM 政策來控制對 API 的存取。
  + `CUSTOM`，以指定您之前建立的 Lambda 授權方函數，藉此實作 API 的授權。授權方可以位於您自己的 AWS 帳戶或其他 AWS 帳戶中。如需 Lambda 授權方的詳細資訊，請參閱 [使用 API Gateway Lambda 授權方](apigateway-use-lambda-authorizer.md)。
**注意**  
在 API Gateway 主控台中，只有在您設定授權方函數 (如 `CUSTOM` 所述) 後，才會看到 [設定 Lambda 授權方 (主控台)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console) 設定。
**重要**  
**Authorization (授權)** 設定會套用至整個 API，不只是 `$connect` 路由。`$connect` 路由會保護其他路由，因為每次連線都會呼叫該路由。
+ **API Key Required (需要 API 金鑰)**：API 的 `$connect` 路由可選擇要求 API 金鑰。您可以同時使用 API 金鑰與用量計劃，以控制並追蹤對 API 的存取。如需更多詳細資訊，請參閱 [API Gateway 中 REST API 的用量計畫和 API 金鑰](api-gateway-api-usage-plans.md)。

### 使用 API Gateway 主控台設定 `$connect` 路由請求
<a name="apigateway-websocket-api-connect-route-request-using-console"></a>

若要使用 API Gateway 主控台來設定 WebSocket API 的 `$connect` 路由請求：

1. 登入 API Gateway 主控台、選擇 API，然後選擇 **Routes (路由)**。

1. 在**路由**下，選擇 `$connect`，或依照 [使用 API Gateway 主控台建立路由](#apigateway-websocket-api-route-using-console) 建立 `$connect` 路由。

1. 在**路由請求設定**區段中，選擇**編輯**。

1. 針對**授權**，選取授權類型。

1. 若要針對 `$connect` 路由要求 API，請選取**需要 API 金鑰**。

1. 選擇**儲存變更**。

# 在 API Gateway 中設定 WebSocket API 的路由回應
<a name="apigateway-websocket-api-route-response"></a>

WebSocket 路由可設定為雙向或單向通訊。API Gateway 不會將後端回應傳遞至路由回應，除非您有設定路由回應。

**注意**  
您只能定義 WebSocket API 的 `$default` 路由回應。您可以使用整合回應來操作後端服務的回應。如需詳細資訊，請參閱[整合回應概觀](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-overview)。

您可以使用 API Gateway 主控台或 AWS CLI 或 AWS SDK 來設定路由回應和回應選取表達式。

如需路由回應選擇表達式的詳細資訊，請參閱 [路由回應選擇表達式](apigateway-websocket-api-selection-expressions.md#apigateway-websocket-api-route-response-selection-expressions)。

**Topics**
+ [使用 API Gateway 主控台設定路由回應](#apigateway-websocket-api-route-response-using-console)
+ [使用 設定路由回應 AWS CLI](#apigateway-websocket-api-route-response-using-awscli)

## 使用 API Gateway 主控台設定路由回應
<a name="apigateway-websocket-api-route-response-using-console"></a>

建立 WebSocket API 並將代理 Lambda 函數附加至預設路由之後，您可以使用 API Gateway 主控台設定路由回應：

1. 登入 API Gateway 主控台，在 `$default` 路由上選擇具備代理 Lambda 函數整合的 WebSocket API。

1. 在 **Routes** (路由) 下選擇 `$default` 路由。

1. 選擇**啟用雙向通訊**。

1. 選擇**部署 API**。

1. 將您的 API 部署至階段。

 使用下列 [ wscat](https://www.npmjs.com/package/wscat) 命令來連線到您的 API。如需 `wscat` 的相關資訊，請參閱 [使用 `wscat` 以連接到 WebSocket API 和將訊息傳送到其中](apigateway-how-to-call-websocket-api-wscat.md)。

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 按下 Enter 按鈕以呼叫預設路由。您 Lambda 函數的主體應該會傳回。

## 使用 設定路由回應 AWS CLI
<a name="apigateway-websocket-api-route-response-using-awscli"></a>

以下 [create-route-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route-response.html) 命令會建立 `$default` 路由的路由回應。您可以使用 [get-apis](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-apis.html) 和 [get-routes](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-routes.html) 命令來識別 API ID 和路由 ID。

```
aws apigatewayv2 create-route-response \
    --api-id aabbccddee \
    --route-id 1122334  \
    --route-response-key '$default'
```

輸出將如下所示：

```
{
    "RouteResponseId": "abcdef",
    "RouteResponseKey": "$default"
}
```

# 設定需要 WebSocket 子協定的 `$connect` 路由
<a name="websocket-connect-route-subprotocol"></a>

用戶端可以使用 `Sec-WebSocket-Protocol` 欄位在連線到您的 WebSocket API 期間請求一個 [WebSocket 子通訊協定](https://datatracker.ietf.org/doc/html/rfc6455#page-12)。您可以設定 `$connect` 路由整合，以允許只有在用戶端請求您的 API 支援的子通訊協定時才允許連線。

下列範例 Lambda 函數會將 `Sec-WebSocket-Protocol` 標題傳回用戶端。只有在用戶端指定 `myprotocol` 子協議時，該函數才會建立到您的 API 的連線。

如需建立此範例 API 和 Lambda 代理整合的 CloudFormation 範本，請參閱 [samples/ws-subprotocol.zip](samples/ws-subprotocol.zip)。

```
export const handler = async (event) => {
    if (event.headers != undefined) {
        const headers = toLowerCaseProperties(event.headers);
        
        if (headers['sec-websocket-protocol'] != undefined) {
            const subprotocolHeader = headers['sec-websocket-protocol'];
            const subprotocols = subprotocolHeader.split(',');
            
            if (subprotocols.indexOf('myprotocol') >= 0) {
                const response = {
                    statusCode: 200,
                    headers: {
                        "Sec-WebSocket-Protocol" : "myprotocol"
                    }
                };
                return response;
            }
        }
    }
    
    const response = {
        statusCode: 400
    };
        
    return response;
};

function toLowerCaseProperties(obj) {
    var wrapper = {};
    for (var key in obj) {
        wrapper[key.toLowerCase()] = obj[key];
    }
    return wrapper;
}
```

您可以使用 [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) 來測試 API 是否允許連線，但只有在用戶端要求您的 API 支援的子通訊協定時才可以。下列命令會使用 `-s` 旗標來指定連線期間的子通訊協定。

下列命令會嘗試使用不受支援的子通訊協定進行連線。因為用戶端指定 `chat1` 子通訊協定，Lambda 整合會傳回 400 錯誤訊息，而且連線失敗。

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1
error: Unexpected server response: 400
```

下列命令在連線要求中包含支援的子通訊協定。Lambda 整合允許連線。

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1,myprotocol
connected (press CTRL+C to quit)
```

若要進一步了解如何叫用 WebSocket API，請參閱[調用 WebSocket API](apigateway-how-to-call-websocket-api.md)。

# 在 API Gateway 中控制和管理對 WebSocket API 的存取
<a name="apigateway-websocket-api-control-access"></a>

API Gateway 支援多種機制來控制和管理對 WebSocket API 的存取。

您可以使用下列機制進行身分驗證和授權：
+ **標準 AWS IAM 角色和政策**提供靈活且強大的存取控制。您可以使用 IAM 角色和原則來控制誰可以建立和管理您的 API，以及誰可以叫用它們。如需更多詳細資訊，請參閱 [使用 IAM 授權控制對 WebSocket API 的存取](apigateway-websocket-control-access-iam.md)。
+ **IAM 標籤**可搭配 IAM 政策一起用來控制存取。如需更多詳細資訊，請參閱 [使用標籤來控制對 API Gateway REST API 資源的存取](apigateway-tagging-iam-policy.md)。
+ **Lambda 授權方** 是控制 API 存取權的 Lambda 函數。如需詳細資訊，請參閱[使用 AWS Lambda REQUEST 授權方控制對 WebSocket APIs存取](apigateway-websocket-api-lambda-auth.md)。

為了改善您的安全狀態，建議您為所有 WebSocket API 上的 `$connect` 路由設定授權方。您可能需要這樣做，才能符合各種合規架構。如需詳細資訊，請參閱《AWS Security Hub 使用者指南》**中的 [Amazon API Gateway 控制項](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)。

**Topics**
+ [使用 IAM 授權控制對 WebSocket API 的存取](apigateway-websocket-control-access-iam.md)
+ [使用 AWS Lambda REQUEST 授權方控制對 WebSocket APIs存取](apigateway-websocket-api-lambda-auth.md)

# 使用 IAM 授權控制對 WebSocket API 的存取
<a name="apigateway-websocket-control-access-iam"></a>

WebSocket API 及 [REST API](api-gateway-control-access-using-iam-policies-to-invoke-api.md) 具備類似的 IAM 授權，除了以下例外：
+ 除了現有動作 (`execute-api`、`ManageConnections`)，`Invoke` 動作也支援 `InvalidateCache`。`ManageConnections` 會控制 @connections API 的存取。
+ WebSocket 路由使用不同的 ARN 格式：

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/route-key
  ```
+ `@connections` API 使用的 ARN 格式與 REST API 相同：

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/POST/@connections
  ```

**重要**  
使用 [IAM 授權](#apigateway-websocket-control-access-iam)時，您必須使用[第 4 版簽署程序 (SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) 來簽署請求。

例如，您可針對用戶端設定下列政策。除了 `Invoke` 階段內的秘密路由，此範例允許所有人針對所有路由傳送訊息 (`prod`)，並防止所有人在任何階段回傳訊息給已連線的用戶端 (`ManageConnections`)。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111122223333:api-id/prod/*"
            ]
        },
        {
            "Effect": "Deny",
            "Action": [
                "execute-api:Invoke"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111122223333:api-id/prod/secret"
            ]
        },
        {
            "Effect": "Deny",
            "Action": [
                "execute-api:ManageConnections"
            ],
            "Resource": [
                "arn:aws:execute-api:us-east-1:111122223333:api-id/*"
            ]
        }
    ]
}
```

------

# 使用 AWS Lambda REQUEST 授權方控制對 WebSocket APIs存取
<a name="apigateway-websocket-api-lambda-auth"></a>

WebSocket API 及 [REST API](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-lambda-function-create) 具備類似的 Lambda 授權方函數，除了以下例外：
+  您只能使用 `$connect` 路由的 Lambda 授權方函數。
+ 您不能使用路徑變數 (`event.pathParameters`)，因為路徑已固定。
+ `event.methodArn` 與同等的 REST API 不同，因其沒有 HTTP 方法。若是 `$connect`，`methodArn` 會以 `"$connect"` 做為結尾：

  ```
  arn:aws:execute-api:region:account-id:api-id/stage-name/$connect
  ```
+ `event.requestContext` 內的內容變數與 REST API 的不同。

 下列範例顯示對 WebSocket API 的 `REQUEST` 授權方的輸入：

```
{
    "type": "REQUEST",
    "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/default/$connect",
    "headers": {
        "Connection": "upgrade",
        "content-length": "0",
        "HeaderAuth1": "headerValue1",
        "Host": "abcdef123.execute-api.us-east-1.amazonaws.com",
        "Sec-WebSocket-Extensions": "permessage-deflate; client_max_window_bits",
        "Sec-WebSocket-Key": "...",
        "Sec-WebSocket-Version": "13",
        "Upgrade": "websocket",
        "X-Amzn-Trace-Id": "...",
        "X-Forwarded-For": "...",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
        "Connection": [
            "upgrade"
        ],
        "content-length": [
            "0"
        ],
        "HeaderAuth1": [
            "headerValue1"
        ],
        "Host": [
            "abcdef123.execute-api.us-east-1.amazonaws.com"
        ],
        "Sec-WebSocket-Extensions": [
            "permessage-deflate; client_max_window_bits"
        ],
        "Sec-WebSocket-Key": [
            "..."
        ],
        "Sec-WebSocket-Version": [
            "13"
        ],
        "Upgrade": [
            "websocket"
        ],
        "X-Amzn-Trace-Id": [
            "..."
        ],
        "X-Forwarded-For": [
            "..."
        ],
        "X-Forwarded-Port": [
            "443"
        ],
        "X-Forwarded-Proto": [
            "https"
        ]
    },
    "queryStringParameters": {
        "QueryString1": "queryValue1"
    },
    "multiValueQueryStringParameters": {
        "QueryString1": [
            "queryValue1"
        ]
    },
    "stageVariables": {},
    "requestContext": {
        "routeKey": "$connect",
        "eventType": "CONNECT",
        "extendedRequestId": "...",
        "requestTime": "19/Jan/2023:21:13:26 +0000",
        "messageDirection": "IN",
        "stage": "default",
        "connectedAt": 1674162806344,
        "requestTimeEpoch": 1674162806345,
        "identity": {
            "sourceIp": "..."
        },
        "requestId": "...",
        "domainName": "abcdef123.execute-api.us-east-1.amazonaws.com",
        "connectionId": "...",
        "apiId": "abcdef123"
    }
}
```

下列範例 Lambda 授權方函數為 [Lambda 授權方函數的其他範例](apigateway-use-lambda-authorizer.md#api-gateway-lambda-authorizer-lambda-function-create) 內 REST API 之 Lambda 授權方函數的 WebSocket 版本：

------
#### [ Node.js ]

```
   // A simple REQUEST authorizer example to demonstrate how to use request 
   // parameters to allow or deny a request. In this example, a request is  
   // authorized if the client-supplied HeaderAuth1 header and QueryString1 query parameter
   // in the request context match the specified values of
   // of 'headerValue1' and 'queryValue1' respectively.
            export const handler = function(event, context, callback) {
    console.log('Received event:', JSON.stringify(event, null, 2));

   // Retrieve request parameters from the Lambda function input:
   var headers = event.headers;
   var queryStringParameters = event.queryStringParameters;
   var stageVariables = event.stageVariables;
   var requestContext = event.requestContext;
       
   // Parse the input for the parameter values
   var tmp = event.methodArn.split(':');
   var apiGatewayArnTmp = tmp[5].split('/');
   var awsAccountId = tmp[4];
   var region = tmp[3];
   var ApiId = apiGatewayArnTmp[0];
   var stage = apiGatewayArnTmp[1];
   var route = apiGatewayArnTmp[2];
       
   // Perform authorization to return the Allow policy for correct parameters and 
   // the 'Unauthorized' error, otherwise.
   var authResponse = {};
   var condition = {};
    condition.IpAddress = {};
    
   if (headers.HeaderAuth1 === "headerValue1"
       && queryStringParameters.QueryString1 === "queryValue1") {
        callback(null, generateAllow('me', event.methodArn));
    }  else {
        callback(null, generateDeny('me', event.methodArn)); 
    }
}
    
// Helper function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
   // Required output:
   var authResponse = {};
    authResponse.principalId = principalId;
   if (effect && resource) {
       var policyDocument = {};
        policyDocument.Version = '2012-10-17		 	 	 '; // default version
       policyDocument.Statement = [];
       var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
       statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
   // Optional output with custom properties of the String, Number or Boolean type.
   authResponse.context = {
       "stringKey": "stringval",
       "numberKey": 123,
       "booleanKey": true
    };
   return authResponse;
}
    
var generateAllow = function(principalId, resource) {
   return generatePolicy(principalId, 'Allow', resource);
}
    
var generateDeny = function(principalId, resource) {
   return generatePolicy(principalId, 'Deny', resource);
}
```

------
#### [ Python ]

```
# A simple REQUEST authorizer example to demonstrate how to use request
# parameters to allow or deny a request. In this example, a request is
# authorized if the client-supplied HeaderAuth1 header and QueryString1 query parameter
# in the request context match the specified values of
# of 'headerValue1' and 'queryValue1' respectively.

import json


def lambda_handler(event, context):
    print(event)

    # Retrieve request parameters from the Lambda function input:
    headers = event['headers']
    queryStringParameters = event['queryStringParameters']
    stageVariables = event['stageVariables']
    requestContext = event['requestContext']

    # Parse the input for the parameter values
    tmp = event['methodArn'].split(':')
    apiGatewayArnTmp = tmp[5].split('/')
    awsAccountId = tmp[4]
    region = tmp[3]
    ApiId = apiGatewayArnTmp[0]
    stage = apiGatewayArnTmp[1]
    route = apiGatewayArnTmp[2]

    # Perform authorization to return the Allow policy for correct parameters
    # and the 'Unauthorized' error, otherwise.

    authResponse = {}
    condition = {}
    condition['IpAddress'] = {}

    if (headers['HeaderAuth1'] ==
            "headerValue1" and queryStringParameters["QueryString1"] == "queryValue1"):
        response = generateAllow('me', event['methodArn'])
        print('authorized')
        return json.loads(response)
    else:
        response = generateDeny('me', event['methodArn'])
        print('unauthorized')
        return json.loads(response)

    # Help function to generate IAM policy


def generatePolicy(principalId, effect, resource):
    authResponse = {}
    authResponse['principalId'] = principalId
    if (effect and resource):
        policyDocument = {}
        policyDocument['Version'] = '2012-10-17		 	 	 '
        policyDocument['Statement'] = []
        statementOne = {}
        statementOne['Action'] = 'execute-api:Invoke'
        statementOne['Effect'] = effect
        statementOne['Resource'] = resource
        policyDocument['Statement'] = [statementOne]
        authResponse['policyDocument'] = policyDocument

    authResponse['context'] = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": True
    }

    authResponse_JSON = json.dumps(authResponse)

    return authResponse_JSON


def generateAllow(principalId, resource):
    return generatePolicy(principalId, 'Allow', resource)


def generateDeny(principalId, resource):
    return generatePolicy(principalId, 'Deny', resource)
```

------

若要將前述 Lambda 函數設定為 WebSocket API 的 `REQUEST` 授權方函數，請遵循 [REST API](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console) 內的相同程序。

若要將 `$connect` 路由在主控台內設定為使用此 Lambda 授權方，請選取或建立 `$connect` 路由。在**路由請求設定**區段中，選擇**編輯**。在**授權**下拉式選單中選取您的授權方，然後選擇**儲存變更**。

欲測試授權方，必須建立新的連線。變更 `$connect` 內的授權方不會影響已經連線的用戶端。連線至您的 WebSocket API 時，必須提供已設定身分來源的值。例如，您可傳送有效查詢字串，標頭使用 `wscat`，藉此進行連線，如下列範例所示：

```
wscat -c 'wss://myapi.execute-api.us-east-1.amazonaws.com/beta?QueryString1=queryValue1' -H HeaderAuth1:headerValue1
```

若您嘗試連線但不具備有效的身分值，將收到 `401` 回應：

```
wscat -c wss://myapi.execute-api.us-east-1.amazonaws.com/beta
error: Unexpected server response: 401
```

# API Gateway 中 WebSocket API 的整合
<a name="apigateway-websocket-api-integrations"></a>

設定 API 路由後，您必須整合它與後端的端點。後端端點也稱為整合端點，可以是 Lambda 函數、HTTP 端點或服務 AWS 動作。API 整合有整合請求和整合回應。

在本節中，您可以了解如何為您的 WebSocket API 設定整合請求和整合回應。

**Topics**
+ [在 API Gateway 中設定一個 WebSocket API 整合請求](apigateway-websocket-api-integration-requests.md)
+ [在 API Gateway 中設定 WebSocket API 整合回應](apigateway-websocket-api-integration-responses.md)

# 在 API Gateway 中設定一個 WebSocket API 整合請求
<a name="apigateway-websocket-api-integration-requests"></a>

設定整合請求包含下列事項：
+ 選擇路由金鑰來整合後端。
+ 指定要調用的後端端點。WebSocket API 支援下列整合類型：
  + `AWS_PROXY`
  + `AWS`
  + `HTTP_PROXY`
  + `HTTP`
  + `MOCK`

  如需整合類型的詳細資訊，請參閱《API Gateway V2 REST API》中的 [IntegrationType](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype)。
+ 視需要指定一個或多個請求範本，設定路由請求資料轉換為整合請求資料的方式。

## 使用 API Gateway 主控台設定 WebSocket API 整合請求
<a name="apigateway-websocket-api-integration-request-using-console"></a>

**使用 API Gateway 主控台在 WebSocket API 內的路由新增整合請求**

1. 登入 API Gateway 主控台、選擇 API，然後選擇 **Routes (路由)**。

1. 在 **Routes (路由)** 底下選擇路由。

1. 選擇**整合請求**索引標籤，然後在**整合請求設定**區段中，選擇**編輯**。

1. 針對**整合類型**，選擇下列其中一項：
   + 只有當您的 API 將與您在此帳戶或其他帳戶中建立的 函數整合時，才選擇 **Lambda** AWS Lambda 函數。

     若要在 中建立新的 Lambda 函數 AWS Lambda、設定 Lambda 函數的資源許可，或執行任何其他 Lambda 服務動作，請改為選擇**AWS 服務**。
   + 若您的 API 將整合現有 HTTP 端點，請選擇 **HTTP (HTTP)**。如需詳細資訊，請參閱 [API Gateway 中 REST API 的 HTTP 整合](setup-http-integrations.md)。
   + 若您希望直接從 API Gateway 產生 API 回應，不使用整合後端，請選擇 **Mock (模擬)**。如需詳細資訊，請參閱[API Gateway 中 REST API 的模擬整合](how-to-mock-integration.md)。
   + 如果您的 API 將與 **AWS 服務**整合，請選擇 AWS 服務。
   + 如果您的 API 將使用 `VpcLink` 做為私有整合端點，請選擇 **VPC 連結**。如需詳細資訊，請參閱 [設定私有整合](set-up-private-integration.md)。

1. 如果您選擇 **Lambda 函數**，請執行下列動作：

   1. 若您希望使用 [Lambda 代理整合](set-up-lambda-proxy-integrations.md#api-gateway-create-api-as-simple-proxy)或[跨帳戶 Lambda 代理整合](apigateway-cross-account-lambda-integrations.md)，請勾選**使用 Lambda 代理整合**核取方塊。

   1. 針對 **Lambda 函數**，以下列方式之一指定函數：
      + 若您的 Lambda 函數位於同一個帳戶，請輸入函數名稱，然後從下拉式清單中選取函數。
**注意**  
函數名稱可選擇納入其別名或版本規格，如 `HelloWorld`、`HelloWorld:1` 或 `HelloWorld:alpha`。
      + 若函數位於不同帳戶，請輸入該函數的 ARN。

   1. 若要使用 29 秒的預設逾時值，請將**預設逾時**保持開啟。若要設定自訂逾時，請選擇**預設逾時**，然後輸入介於 `50` 和 `29000` 毫秒之間的逾時值。

1. 若您選擇 **HTTP (HTTP)**，請依照 [使用 API Gateway 主控台設定 API 整合請求](how-to-method-settings-console.md) 步驟 4 的指示。

1. 若您選擇 **Mock (模擬)**，請前往 **Request Templates (請求範本)** 步驟。

1. 若您選擇 **AWS 服務**，請依照 [使用 API Gateway 主控台設定 API 整合請求](how-to-method-settings-console.md) 的步驟 6 的指示進行。

1. 若您選擇 **VPC 連結**，請執行下列動作：

   1. 若您希望將請求代理到 `VPCLink` 端點，請勾選 **VPC 代理整合**核取方塊。

   1. 針對 **HTTP method (HTTP 方法)**，選擇最符合 HTTP 後端中方法的 HTTP 方法類型。

   1. 從 **VPC 連結**下拉式清單中，選取 VPC 連結。您可以在清單下方的文字方塊中選取 `[Use Stage Variables]` 並輸入 **\$1\$1stageVariables.vpcLinkId\$1**。

      將 API 部署到階段後，您就可以定義 `vpcLinkId` 階段變數，並將其值設定為 `VpcLink` 的 ID。

   1. 針對 **Endpoint URL (端點 URL)**，請輸入您希望此整合使用之 HTTP 後端的 URL。

   1. 若要使用 29 秒的預設逾時值，請將**預設逾時**保持開啟。若要設定自訂逾時，請選擇**預設逾時**，然後輸入介於 `50` 和 `29000` 毫秒之間的逾時值。

1. 選擇**儲存變更**。

1. 在**請求範本**下，執行下列動作：

   1. 在**請求範本**下選擇**編輯**，以輸入**範本選擇表達式**。

   1. 輸入**範本選擇表達式**。使用 API Gateway 在訊息承載中尋找的表達式。若找到將對其評估，而結果範本金鑰值將用於選取在訊息承載內套用至資料的資料映射範本。您會在下一個步驟中建立資料映射範本。選擇**編輯**，儲存您的變更。

   1. 選擇**建立範本**，以建立資料映射範本。針對**範本金鑰**輸入範本金鑰值，該值將用來選取要對訊息承載中的資料套用的資料映射範本。接著，輸入映射範本。選擇**建立範本**。

      如需範本選擇表達式的相關資訊，請參閱 [範本選擇表達式](websocket-api-data-transformations.md#apigateway-websocket-api-template-selection-expressions)。

## 使用 設定整合請求 AWS CLI
<a name="apigateway-websocket-api-integration-request-using-awscli"></a>

您可使用 AWS CLI 設定 WebSocket API 內路由的整合請求，建立模擬整合，如下列範例所示：

1. 建立名為 `integration-params.json` 的檔案，其中內容如下：

   ```
   {"PassthroughBehavior": "WHEN_NO_MATCH", "TimeoutInMillis": 29000, "ConnectionType": "INTERNET", "RequestTemplates": {"application/json": "{\"statusCode\":200}"}, "IntegrationType": "MOCK"}
   ```

1. 使用下列 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令來建立模擬整合。

   ```
   aws apigatewayv2 --region us-east-1 create-integration --api-id aabbccddee --cli-input-json file://integration-params.json
   ```

   輸出將如下所示：

   ```
   {
       "PassthroughBehavior": "WHEN_NO_MATCH",
       "TimeoutInMillis": 29000,
       "ConnectionType": "INTERNET",
       "IntegrationResponseSelectionExpression": "${response.statuscode}",
       "RequestTemplates": {
           "application/json": "{\"statusCode\":200}"
       },
       "IntegrationId": "0abcdef",
       "IntegrationType": "MOCK"
   }
   ```

或者，您可以使用 設定代理整合的整合請求 AWS CLI。

1. 在 Lambda 主控台中建立 Lambda 函數，並賦予基本的 Lambda 執行角色。

1. 使用下列 [create-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration.html) 命令來建立整合。

   ```
   aws apigatewayv2 create-integration --api-id aabbccddee --integration-type AWS_PROXY --integration-method POST --integration-uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123412341234:function:simpleproxy-echo-e2e/invocations
   ```

輸出將如下所示：

```
{
    "PassthroughBehavior": "WHEN_NO_MATCH",
    "IntegrationMethod": "POST",
    "TimeoutInMillis": 29000,
    "ConnectionType": "INTERNET",
    "IntegrationUri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123412341234:function:simpleproxy-echo-e2e/invocations",
    "IntegrationId": "abcdefg",
    "IntegrationType": "AWS_PROXY"
}
```

## WebSocket API 之代理整合的 Lambda 函數的輸入格式
<a name="api-gateway-simple-proxy-for-lambda-input-format-websocket"></a>

在 Lambda 代理整合中，API Gateway 會將整個用戶端請求映射至後端 Lambda 函數的輸入 `event` 參數。下列範例顯示來自 `$connect` 路由的輸入事件結構，以及來自 API Gateway 傳送至 Lambda 代理整合之 `$disconnect` 路由的輸入事件結構。

------
#### [ Input from the \$1connect route ]

```
{
    headers: {
      Host: 'abcd123.execute-api.us-east-1.amazonaws.com',
      'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
      'Sec-WebSocket-Key': '...',
      'Sec-WebSocket-Version': '13',
      'X-Amzn-Trace-Id': '...',
      'X-Forwarded-For': '192.0.2.1',
      'X-Forwarded-Port': '443',
      'X-Forwarded-Proto': 'https'
    },
    multiValueHeaders: {
      Host: [ 'abcd123.execute-api.us-east-1.amazonaws.com' ],
      'Sec-WebSocket-Extensions': [ 'permessage-deflate; client_max_window_bits' ],
      'Sec-WebSocket-Key': [ '...' ],
      'Sec-WebSocket-Version': [ '13' ],
      'X-Amzn-Trace-Id': [ '...' ],
      'X-Forwarded-For': [ '192.0.2.1' ],
      'X-Forwarded-Port': [ '443' ],
      'X-Forwarded-Proto': [ 'https' ]
    },
    requestContext: {
      routeKey: '$connect',
      eventType: 'CONNECT',
      extendedRequestId: 'ABCD1234=',
      requestTime: '09/Feb/2024:18:11:43 +0000',
      messageDirection: 'IN',
      stage: 'prod',
      connectedAt: 1707502303419,
      requestTimeEpoch: 1707502303420,
      identity: { sourceIp: '192.0.2.1' },
      requestId: 'ABCD1234=',
      domainName: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      connectionId: 'AAAA1234=',
      apiId: 'abcd1234'
    },
    isBase64Encoded: false
  }
```

------
#### [ Input from the \$1disconnect route ]

```
{
    headers: {
      Host: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      'x-api-key': '',
      'X-Forwarded-For': '',
      'x-restapi': ''
    },
    multiValueHeaders: {
      Host: [ 'abcd1234.execute-api.us-east-1.amazonaws.com' ],
      'x-api-key': [ '' ],
      'X-Forwarded-For': [ '' ],
      'x-restapi': [ '' ]
    },
    requestContext: {
      routeKey: '$disconnect',
      disconnectStatusCode: 1005,
      eventType: 'DISCONNECT',
      extendedRequestId: 'ABCD1234=',
      requestTime: '09/Feb/2024:18:23:28 +0000',
      messageDirection: 'IN',
      disconnectReason: 'Client-side close frame status not set',
      stage: 'prod',
      connectedAt: 1707503007396,
      requestTimeEpoch: 1707503008941,
      identity: { sourceIp: '192.0.2.1' },
      requestId: 'ABCD1234=',
      domainName: 'abcd1234.execute-api.us-east-1.amazonaws.com',
      connectionId: 'AAAA1234=',
      apiId: 'abcd1234'
    },
    isBase64Encoded: false
  }
```

------

# 在 API Gateway 中設定 WebSocket API 整合回應
<a name="apigateway-websocket-api-integration-responses"></a>

下一節提供有關 WebSocket API 整合回應的簡短概觀，以及如何設定 WebSocket API 整合回應。

**Topics**
+ [整合回應概觀](#apigateway-websocket-api-integration-response-overview)
+ [雙向通訊的整合回應](#apigateway-websocket-api-integration-response-for-two-way-communication)
+ [使用 API Gateway 主控台設定整合回應](#apigateway-websocket-api-integration-response-using-console)
+ [使用 設定整合回應 AWS CLI](#apigateway-websocket-api-integration-response-using-awscli)

## 整合回應概觀
<a name="apigateway-websocket-api-integration-response-overview"></a>

API Gateway 的整合回應是從後端服務建模並操控回應的方式。REST API 與 WebSocket API 整合回應的設定方式有些許差異，但概念上的行為相同。

WebSocket 路由可設定為雙向或單向通訊。
+ 路由設定為雙向通訊時，整合回應可讓您設定回傳訊息承載的轉換，類似 REST API 的整合回應。
+ 若路由設定為單向通訊，則不論整合回應的設定為何，WebSocket 管道在訊息處理後都不會回傳回應。

 API Gateway 不會將後端回應傳遞至路由回應，除非您有設定路由回應。若要了解設定路由回應，請參閱 [在 API Gateway 中設定 WebSocket API 的路由回應](apigateway-websocket-api-route-response.md)。

## 雙向通訊的整合回應
<a name="apigateway-websocket-api-integration-response-for-two-way-communication"></a>

整合可分為*代理*整合和*非代理*整合。

**重要**  
以*代理整合*而言，API Gateway 會自動將後端輸出以完整的承載傳遞至發起人。此時沒有整合回應。

以*非代理整合*而言，您必須設定至少一個整合回應：
+ 在沒有明確選擇時，其中一個整合回應最好設定為全部截獲。將整合回應金鑰設定為 `$default` 就是此預設案例的代表。
+ 在其他情況下，整合回應金鑰會以常規表達式運作，應遵循 `"/expression/"` 的格式。

以非代理 HTTP 整合而言：
+ API Gateway 將嘗試比對後端回應的 HTTP 狀態碼。整合回應金鑰此時會以常規表達式運作，若找不到配對項目，將選擇 `$default` 做為整合回應。
+ 範本選擇表達式運作方式完全相同，如上所述。例如：
  + `/2\d\d/`：接收並轉換成功的回應
  + `/4\d\d/`：接收並轉換不正確的請求錯誤
  + `$default`：接收並轉換所有意外回應

如需範本選擇表達式的更多資訊，請參閱 [範本選擇表達式](websocket-api-data-transformations.md#apigateway-websocket-api-template-selection-expressions)。

## 使用 API Gateway 主控台設定整合回應
<a name="apigateway-websocket-api-integration-response-using-console"></a>

使用 API Gateway 主控台設定 WebSocket API 的路由整合回應：

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1.  選擇您的 WebSocket API 並選擇您的路由。

1. 選擇**整合請求**索引標籤，然後在**整合回應設定**區段中，選擇**建立整合回應**。

1. 在**回應金鑰**中輸入值，此值將可在評估回應選擇表達式之後，於傳出訊息的回應金鑰中找到。例如，您可以輸入 **/4\$1d\$1d/** 來接收和轉換錯誤的請求錯誤，或者輸入 **\$1default** 來接收並轉換符合範本選擇表達式的所有回應。

1. 在**範本選擇表達式**中，輸入選擇表達式以評估傳出訊息。

1. 選擇**建立回應**。

1. 您也可以定義對應範本，以設定傳回訊息承載的轉換。選擇**建立範本**。

1. 輸入金鑰名稱。如果您要選擇預設範本選擇表達式，請輸入 **\$1\$1default**。

1. 在程式碼編輯器中，針對**回應範本**輸入您的映射範本。

1. 選擇**建立範本**。

1. 選擇**部署 API** 以部署您的 API。

 使用下列 [ wscat](https://www.npmjs.com/package/wscat) 命令來連線到您的 API。如需 `wscat` 的相關資訊，請參閱 [使用 `wscat` 以連接到 WebSocket API 和將訊息傳送到其中](apigateway-how-to-call-websocket-api-wscat.md)。

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 當您呼叫路由時，傳回的訊息承載應傳回。

## 使用 設定整合回應 AWS CLI
<a name="apigateway-websocket-api-integration-response-using-awscli"></a>

以下 [create-integration-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-integration-response.html) 命令會建立 `$default` 整合回應：

```
aws apigatewayv2 create-integration-response \
    --api-id vaz7da96z6 \
    --integration-id a1b2c3 \
    --integration-response-key '$default'
```

# 請求驗證 API Gateway 中的 WebSocket API
<a name="websocket-api-request-validation"></a>

您可以將 API Gateway 設定為對路由執行驗證，再繼續進行整合請求。如果驗證失敗，API Gateway 的請求失敗，而不呼叫後端、傳送與以下用戶端類似的「錯誤的請求內文」閘道回應，以及在 CloudWatch Logs 中發布驗證結果。以這種方式使用驗證減少對 API 後端的不必要呼叫。

## 模型選擇表達式
<a name="apigateway-websocket-api-model-selection-expressions"></a>

您可以使用模型選擇表示式來動態驗證相同路由內的請求。如果您為代理或非代理整合提供模型選取表示式，就會發生模型驗證。找不到相符的模型時，您可能需要將 `$default` 模型定義為回復。如果沒有相符的模型，而且沒有定義 `$default`，驗證會失敗。選取表示式看起來類似 `Route.ModelSelectionExpression` 並評估為 `Route.RequestModels` 的索引鍵。

當您定義 WebSocket API 的路由時，您可以選擇指定*模型選取表達*式。評估此表達式後，即可選取接收請求時將用於內文驗證的模型。此運算式的判斷值為路由的 [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes.html#apis-apiid-routes-prop-route-requestmodels](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes.html#apis-apiid-routes-prop-route-requestmodels) 其中一個項目。

模型是以 [JSON 結構描述](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04)來表示，並描述請求本文的資料結構。此選擇表達式本身讓您能夠動態選擇欲用來在執行時間驗證特定路由的模型。如需建立模型的資訊，請參閱 [REST API 的資料模型](models-mappings-models.md)。

## 使用 API Gateway 主控台設定請求驗證
<a name="apigateway-websocket-api-model-selection-expression-example"></a>

下列範例說明何在路由上設定請求驗證。

 首先，建立模型，然後建立路由。接著，在剛建立的路由上設定請求驗證。最後，部署並測試 API。若要完成本教學課程，您需要 WebSocket API 搭配 `$request.body.action` 做為新路由的路由選擇表達式和整合端點。

您還需要 `wscat` 來連線到 API。如需詳細資訊，請參閱[使用 `wscat` 以連接到 WebSocket API 和將訊息傳送到其中](apigateway-how-to-call-websocket-api-wscat.md)。

**建立裝置**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇 WebSocket API。

1. 在主導覽窗格中，選擇**模型**。

1. 選擇**建立模型**。

1. 對於**名稱**，輸入 **emailModel**。

1. 針對**內容類型**，輸入 **application/json**。

1. 針對**模型結構描述**，輸入下列模型：

   ```
   {
       "$schema": "http://json-schema.org/draft-04/schema#",
       "type" : "object",
       "required" : [ "address"],
       "properties" : {
           "address": {
               "type": "string"
           }
       }
   }
   ```

   此模型要求該請求應包含電子郵件地址。

1. 選擇**儲存**。

在此步驟中，為 WebSocket API 建立路由。

**建立路由**

1. 在主要導覽窗格中，選擇**路由**。

1. 選擇 **Create route (建立路由)**。

1. 對於 **Route key (路由金鑰)**，輸入 **sendMessage**。

1. 選擇整合類型並指定整合端點。如需更多資訊，請參閱[API Gateway 中 WebSocket API 的整合](apigateway-websocket-api-integrations.md)。

1. 選擇 **Create route (建立路由)**。

在此步驟中，設定 `sendMessage` 路由的請求驗證。

**設定請求驗證**

1. 在**路由請求**標籤的**路由請求設定**下，選擇**編輯**。

1. 針對**模型選取表達式**，輸入 **\$1\$1request.body.messageType\$1**。

   API Gateway 使用 `messageType` 屬性驗證傳入的請求。

1. 選擇**新增請求模型**。

1. 對於**模型金鑰**，輸入 **email**。

1. 對於**模型**，選擇 **emailModel**。

   針對此模型，API Gateway 會以 `messageType` 屬性設定為 `email` 的方式來驗證傳入的訊息。
**注意**  
如果 API Gateway 無法將模型選取表達式與模型金鑰相配，便會選取 `$default` 模型。如果沒有 `$default` 模型，則驗證會失敗。對於生產 API，我們建議您建立 `$default` 模型。

1. 選擇**儲存變更**。

在此步驟中，您會部署和測試 API。

**部署和測試 API**

1. 選擇**部署 API**。

1. 從下拉式清單中選擇所需的階段，或輸入新階段的名稱。

1. 選擇**部署**。

1. 在主導覽窗格中，選擇**階段**。

1. 複製 API 的 WebSocket URL。URL 看起來應該會像這樣：`wss://abcdef123.execute-api.us-east-2.amazonaws.com/production`。

1. 開啟新的終端機，並使用下列參數執行 **wscat** 命令。

   ```
   wscat -c wss://abcdef123.execute-api.us-west-2.amazonaws.com/production
   ```

   ```
   Connected (press CTRL+C to quit)
   ```

1. 使用下列命令測試 API。

   ```
   {"action": "sendMessage", "messageType": "email"}
   ```

   ```
   {"message": "Invalid request body", "connectionId":"ABCD1=234", "requestId":"EFGH="}
   ```

   API Gateway 將使請求無法過關。

   使用下一個命令，將有效的請求傳送至您的 API。

   ```
   {"action": "sendMessage", "messageType": "email", "address": "mary_major@example.com"}
   ```

# API Gateway 中用於 WebSocket API 的資料轉換
<a name="websocket-api-data-transformations"></a>

在 API Gateway 中，WebSocket API 的方法請求可視後端的需求，從對應的整合請求承載擷取不同格式的承載。同樣地，後端可能會依照前端的預期，傳回與方法回應承載不同的整合回應承載。

API Gateway 可讓您使用映射範本轉換，將承載從方法請求映射至對應的整合請求，以及從整合回應映射至對應的方法回應。您會建立映射範本並指定範本選擇表達式，以決定要使用哪個範本來執行必要的資料轉換。

您可以使用資料映射，將 [路由請求](api-gateway-basic-concept.md#apigateway-definition-route-request) 中的資料映射至後端整合。如需進一步了解，請參閱[設定 API Gateway 中 WebSocket API 的資料映射](websocket-api-data-mapping.md)。

## 對應範本和模型
<a name="apigateway-websocket-api-mapping-templats-and-models"></a>

 *對應範本*是以 [Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 表示，並使用 [JSONPath 表達式](https://goessner.net/articles/JsonPath/)套用至承載的指令碼。如需 API Gateway 對應範本的詳細資訊，請參閱 [API Gateway 中 REST API 的映射範本轉換](models-mappings.md)。

根據 [JSON 結構描述草稿第 4 版](https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04)，承載可以有一個*資料模型*。您不需要定義任何模型，即可建立對應範本。不過，模型可協助您建立範本，因為 API Gateway 會根據提供的模型產生範本藍圖。如需 API Gateway 模型的詳細資訊，請參閱 [REST API 的資料模型](models-mappings-models.md)。

## 範本選擇表達式
<a name="apigateway-websocket-api-template-selection-expressions"></a>

若要使用對應範本轉換承載，您可以[整合請求](apigateway-websocket-api-integration-requests.md)或[整合回應](apigateway-websocket-api-integration-responses.md)中指定 WebSocket API 範本選取運算式。此表達式的評估結果會判定輸入或輸出範本 (如有)，輸入範本可將請求本文轉換為整合請求本文，輸出範本則可將整合回應本文轉換為路由回應本文。

`Integration.TemplateSelectionExpression` 支援 `${request.body.jsonPath}` 和靜態值。

`IntegrationResponse.TemplateSelectionExpression` 支援 `${request.body.jsonPath}`、`${integration.response.statuscode}`、`${integration.response.header.headerName}`、`${integration.response.multivalueheader.headerName}` 和靜態值。

## 整合回應選擇表達式
<a name="apigateway-websocket-api-integration-response-selection-expressions"></a>

[設定 WebSocket API 的整合回應](apigateway-websocket-api-integration-responses.md)時，您可選擇指定整合回應選擇表達式。此運算式會判定整合回傳時應選取的 `[https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid-integrationresponses-integrationresponseid.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid-integrationresponses-integrationresponseid.html)`。此表達式的值目前正受 API Gateway 限制，規則如下。請注意，此表達式只與*非代理整合*有關；代理整合只要將回應承載回傳給發起人即可，無須建模或修改。

此表達式與上述選擇表達式不同，目前支援*模式比對*格式。此表達式應以斜線包裝。

目前固定的值視 `[https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-integrations-integrationid.html#apis-apiid-integrations-integrationid-prop-integration-integrationtype)` 而異：
+ 若是 Lambda 型整合，此值為 `$integration.response.body.errorMessage`。
+ 若是 `HTTP` 及 `MOCK` 整合，此值為 `$integration.response.statuscode`。
+ 若是 `HTTP_PROXY` 及 `AWS_PROXY`，將不會運用此表達式，因為您請求將承載傳遞給發起人。

# 設定 API Gateway 中 WebSocket API 的資料映射
<a name="websocket-api-data-mapping"></a>

*資料映射*可讓您將[路由請求](api-gateway-basic-concept.md#apigateway-definition-route-request)中的資料映射至後端整合。

**注意**  
不支援 WebSocket APIs的資料映射 AWS 管理主控台。您必須使用 AWS CLI AWS CloudFormation、 或 SDK 來設定資料映射。

**Topics**
+ [將路由請求資料對應到整合請求參數](#websocket-mapping-request-parameters)
+ [範例](#websocket-data-mapping-examples)

## 將路由請求資料對應到整合請求參數
<a name="websocket-mapping-request-parameters"></a>

整合請求參數可以從任何定義的路由請求參數，請求內文、[`context`](api-gateway-mapping-template-reference.md#context-variable-reference) 或 [`stage`](api-gateway-mapping-template-reference.md#stagevariables-template-reference) 的變量，以及靜態值進行映射。

下表展示整合請求資料映射表達式。在下表中，*`PARAM_NAME`* 是指定參數類型的路由請求參數的名稱。它必須符合規則表達式 `'^[a-zA-Z0-9._$-]+$]'`。*JSONPath\$1EXPRESSION* 是請求內文的 JSON 欄位的 JSONPath 表達式。


| 映射的資料來源 | 對應表達式 | 
| --- | --- | 
| 請求查詢字串 (僅支援 \$1connect 路由) | route.request.querystring.PARAM\$1NAME | 
| 請求標頭 (僅支援 \$1connect 路由) | route.request.header.PARAM\$1NAME | 
| 多值請求查詢字串 (僅支援 \$1connect 路由) | route.request.multivaluequerystring.PARAM\$1NAME | 
| 多值請求標頭 (僅支援 \$1connect 路由) | route.request.multivalueheader.PARAM\$1NAME | 
| 請求內文 | route.request.body.JSONPath\$1EXPRESSION | 
| 階段變數 | stageVariables.VARIABLE\$1NAME | 
| 環境變數 | context.VARIABLE\$1NAME 必須是[支援的環境變數](api-gateway-mapping-template-reference.md#context-variable-reference)之一。 | 
| 靜態值 | 'STATIC\$1VALUE'。STATIC\$1VALUE 是字串常值，而且必須以一對單引號括住。 | 

當您建立資料映射時，使用 AWS CLI 時，請務必遵循在 中使用常值與字串的正確格式 AWS CLI。如需詳細資訊，請參閱《AWS Command Line Interface 使用者指南》**中的[搭配 AWS CLI中的字串使用引號和常值](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-quoting-strings.html)。

## 範例
<a name="websocket-data-mapping-examples"></a>

下列 AWS CLI 範例會設定資料映射。如需範例 CloudFormation 範本，請參閱 [samples/websocket-data-mapping.zip](samples/websocket-data-mapping.zip)。

### 將用戶端的連線 ID 映射至整合請求中的標頭
<a name="websocket-data-mapping-examples.connectionId"></a>

以下 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-integration.html) 命令會將用戶端的 `connectionId` 映射至後端整合請求中的 `connectionId` 標頭：

```
aws apigatewayv2 update-integration \
    --integration-id abc123 \
    --api-id a1b2c3d4 \ 
    --request-parameters 'integration.request.header.connectionId'='context.connectionId'
```

### 將查詢字串參數映射至整合請求中的標頭
<a name="websocket-data-mapping-examples.querystring"></a>

下列範例會將 `authToken` 查詢字串參數映射至整合請求中的 `authToken` 標頭。

1. 使用下列 [update-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-route.html) 命令，將 `authToken` 查詢字串參數新增至路由的請求參數。

   ```
   aws apigatewayv2 update-route --route-id 0abcdef \
       --api-id a1b2c3d4 \
       --request-parameters '{"route.request.querystring.authToken": {"Required": false}}'
   ```

1.  使用下列 [update-integration](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-integration.html) 命令，將查詢字串參數映射至後端整合請求中的 `authToken` 標頭。

   ```
   aws apigatewayv2 update-integration \
       --integration-id abc123 \
       --api-id a1b2c3d4 \
       --request-parameters 'integration.request.header.authToken'='route.request.querystring.authToken'
   ```

1. (選用) 如有必要，使用下列 [delete-route-request-parameter](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/delete-route-request-parameter.html) 從路由的請求參數中刪除 `authToken` 查詢字串參數。

   ```
   aws apigatewayv2 delete-route-request-parameter \
       --route-id 0abcdef \
       --api-id a1b2c3d4 \
       --request-parameter-key 'route.request.querystring.authToken'
   ```

# 用於 API Gateway 的 WebSocket API 映射範本參考
<a name="apigateway-websocket-api-mapping-template-reference"></a>

此章節摘要說明目前 API Gateway 內 WebSocket API 支援的變數組。


| 參數 | 描述 | 
| --- | --- | 
| \$1context.connectionId |  連線的唯一 ID，可用來回呼用戶端。  | 
| \$1context.connectedAt |  [Epoch](https://en.wikipedia.org/wiki/Unix_time) 格式化連線時間。  | 
| \$1context.domainName |  WebSocket API 的網域名稱。此可用於回呼用戶端 (非硬式編碼的值)。  | 
| \$1context.eventType |  事件類型：`CONNECT`、`MESSAGE` 或 `DISCONNECT`。  | 
| \$1context.messageId |  訊息的伺服器端唯一 ID。僅在 `$context.eventType` 為 `MESSAGE` 時可用。  | 
| \$1context.routeKey |  所選路由金鑰。  | 
| \$1context.requestId |  與 `$context.extendedRequestId` 相同。  | 
| \$1context.extendedRequestId | API 呼叫的自動產生的 ID，其中包含更多除錯/故障排除的有用的資訊。 | 
| \$1context.apiId |  API Gateway 指派給您 API 的識別碼。  | 
| \$1context.authorizer.principalId |  與用戶端所傳送並從 API Gateway Lambda 授權方 (先前稱作自訂授權方) Lambda 函數所傳回之權杖建立關聯的主要使用者識別。  | 
| \$1context.authorizer.property |  API Gateway Lambda 授權方函數所傳回 `context` 映射之指定索引鍵/值組的字串化值。例如，如果授權方傳回下列 `context` 映射： <pre>"context" : {<br />  "key": "value",<br />  "numKey": 1,<br />  "boolKey": true<br />}</pre> 呼叫 `$context.authorizer.key` 會傳回 `"value"` 字串、呼叫 `$context.authorizer.numKey` 會傳回 `"1"` 字串，而呼叫 `$context.authorizer.boolKey` 會傳回 `"true"` 字串。  | 
| \$1context.error.messageString | \$1context.error.message 的引用值，即 "\$1context.error.message"。 | 
| \$1context.error.validationErrorString |  字串，其中包含詳細的驗證錯誤訊息。  | 
| \$1context.identity.accountId |  與請求相關聯的 AWS 帳戶 ID。  | 
| \$1context.identity.apiKey |  與啟用金鑰之 API 請求建立關聯的 API 擁有者金鑰。  | 
| \$1context.identity.apiKeyId | 與啟用金鑰之 API 請求建立關聯的 API 金鑰 ID。 | 
| \$1context.identity.caller |  提出請求之發起人的委託人識別符。  | 
| \$1context.identity.cognitoAuthenticationProvider |  提出請求的發起人所使用的所有 Amazon Cognito 驗證提供者清單 (以逗號分隔)。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。 例如，適用於 Amazon Cognito 使用者集區的身分，`cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` 如需有關 Amazon Cognito 驗證提供者的詳細資訊，請參閱《[Amazon Cognito 開發人員指南](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)》中的*使用聯合身分*。 | 
| \$1context.identity.cognitoAuthenticationType |  提出請求的發起人的 Amazon Cognito 驗證類型。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。可能的值包括用於已驗證身分的 `authenticated` 和未經驗證身分的 `unauthenticated`。 | 
| \$1context.identity.cognitoIdentityId |  提出請求的發起人的 Amazon Cognito 身分 ID。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。  | 
| \$1context.identity.cognitoIdentityPoolId |  提出請求的發起人的 Amazon Cognito 身分集區 ID。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。  | 
| \$1context.identity.sourceIp |  對 API Gateway 提出請求之即時 TCP 連線的來源 IP 地址。  | 
| \$1context.identity.user |  提出請求之使用者的委託人識別符。  | 
| \$1context.identity.userAgent |  API 發起人的使用者代理程式。  | 
| \$1context.identity.userArn |  身分驗證之後識別之有效使用者的 Amazon Resource Name (ARN)。  | 
| \$1context.requestTime | [CLF](https://httpd.apache.org/docs/current/logs.html#common) 格式化請求時間 (dd/MMM/yyyy:HH:mm:ss \$1-hhmm)。 | 
| \$1context.requestTimeEpoch | [Epoch](https://en.wikipedia.org/wiki/Unix_time) 格式化的要求時間，以毫秒為單位。 | 
| \$1context.stage |  API 呼叫的部署階段 (例如，Beta 或 Prod)。  | 
| \$1context.status |  回應狀態。  | 
| \$1input.body | 傳回原始承載作為字串。 | 
| \$1input.json(x) | 此函數會評估 JSONPath 表達式，並傳回結果作為 JSON 字串。 例如，`$input.json('$.pets')` 會傳回代表 pets 結構的 JSON 字串。 如需 JSONPath 的詳細資訊，請參閱 [JSONPath](https://goessner.net/articles/JsonPath/) 或[適用於 Java 的 JSONPath](https://github.com/json-path/JsonPath)。 | 
| \$1input.path(x) | 採用 JSONPath 表達式字串 (`x`)，並傳回結果的 JSON 物件呈現。這可讓您存取和運用 [Apache Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) 中原生承載的元素。 例如，如果表達式 `$input.path('$.pets')` 傳回如下物件： <pre>[<br />  { <br />    "id": 1, <br />    "type": "dog", <br />    "price": 249.99 <br />  }, <br />  { <br />    "id": 2, <br />    "type": "cat", <br />    "price": 124.99 <br />  }, <br />  { <br />    "id": 3, <br />    "type": "fish", <br />    "price": 0.99 <br />  } <br />]</pre> `$input.path('$.pets').count()` 會傳回 `"3"`。 如需 JSONPath 的詳細資訊，請參閱 [JSONPath](http://goessner.net/articles/JsonPath/) 或[適用於 Java 的 JSONPath](https://github.com/jayway/JsonPath)。 | 
| \$1stageVariables.<variable\$1name> |  *<variable\$1name>* 代表階段變數名稱。  | 
| \$1stageVariables['<variable\$1name>'] |  *<variable\$1name>* 代表任何階段變數名稱。  | 
| \$1\$1stageVariables['<variable\$1name>']\$1 |  *<variable\$1name>* 代表任何階段變數名稱。  | 
| \$1util.escapeJavaScript() |  使用 JavaScript 字串規則來逸出字串中的字元。  此函數會將任何一般單引號 (`'`) 轉換為逸出單引號 (`\'`)。不過，逸出單引號不適用於 JSON。因此，將此函數的輸出用於 JSON 屬性時，您必須將任何逸出單引號 (`\'`) 轉換為一般單引號 (`'`)。下列範例顯示這種情況： <pre> $util.escapeJavaScript(data).replaceAll("\\'","'")</pre>   | 
| \$1util.parseJson() |   採用「字串化」JSON，並傳回結果的物件呈現。您可以使用此函數的結果，來存取和運用 Apache Velocity 範本語言 (VTL) 中原生承載的元素。例如，如果您有下列承載： <pre>{"errorMessage":"{\"key1\":\"var1\",\"key2\":{\"arr\":[1,2,3]}}"}</pre>  並使用下列映射範本  <pre>#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))<br />{<br />   "errorMessageObjKey2ArrVal" : $errorMessageObj.key2.arr[0]<br />}<br /></pre> 您將會收到下列輸出： <pre>{<br />   "errorMessageObjKey2ArrVal" : 1<br />}<br /></pre>  | 
| \$1util.urlEncode() | 將字串轉換為 "application/x-www-form-urlencoded" 格式。 | 
| \$1util.urlDecode() | 解碼 "application/x-www-form-urlencoded" 字串。 | 
| \$1util.base64Encode() | 將資料編碼為 base64 編碼字串。 | 
| \$1util.base64Decode() | 解碼 base64 編碼字串中的資料。 | 

# API Gateway 中 WebSocket API 的二進位媒體類型
<a name="websocket-api-develop-binary-media-types"></a>

API Gateway WebSocket API 在內送訊息承載中目前不支援二進位影格。如果用戶端應用程式傳送的是二進位影格，API Gateway 會拒絕接收和中斷與用戶端的連線並出現程式碼 1003。

此行為有一個解決方法。如果用戶端傳送文字編碼的二進位資料 (例如，Base64) 做為文字框架，您可以將整合的 `contentHandlingStrategy` 屬性設定為 `CONVERT_TO_BINARY`，以從 Base64 編碼字串的承載轉換到二進位。

要為非 Proxy 整合二進位承載傳回路由回應，您可以將整合回應的 `contentHandlingStrategy` 屬性設定為 `CONVERT_TO_TEXT`，以從二進位到的承載轉換 Base64 編碼字串。

# 調用 WebSocket API
<a name="apigateway-how-to-call-websocket-api"></a>

在您部署 WebSocket API 之後，用戶端應用程式可以連接到其中和傳送訊息，且後端服務可將訊息傳送到連線的用戶端應用程式：
+ 您可以使用 `wscat` 來連接 WebSocket API 和將訊息傳送到其中，以模擬用戶端行為。請參閱[使用 `wscat` 以連接到 WebSocket API 和將訊息傳送到其中](apigateway-how-to-call-websocket-api-wscat.md)。
+ 您可以從後端服務使用 @connections API，來將回呼訊息傳送到連線用戶端、取得連線資訊，或中斷用戶端。請參閱[在後端服務使用 `@connections` 命令](apigateway-how-to-call-websocket-api-connections.md)。
+ 用戶端應用程式可以使用自己的 WebSocket 程式庫來叫用 WebSocket API。

# 使用 `wscat` 以連接到 WebSocket API 和將訊息傳送到其中
<a name="apigateway-how-to-call-websocket-api-wscat"></a>

`[wscat](https://www.npmjs.com/package/wscat)` 公用程式是一種便捷的工具，適用於測試在 API Gateway 中建立和部署的 WebSocket API。您可以如下安裝和使用 `wscat`：

1. 從 [https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat) 下載 `wscat`。

1. 執行下列命令來安裝 `wscat`：

   ```
   npm install -g wscat
   ```

1. 若要連線到 API，如下列命令範例所示，執行 `wscat` 命令。請注意，這個範例假設 `Authorization` 設定是 `NONE`。

   ```
   wscat -c wss://aabbccddee.execute-api.us-east-1.amazonaws.com/test/
   ```

   您需要使用實際 API ID 取代 `aabbccddee`，該 ID 會顯示在 API Gateway 主控台中或由 AWS CLI [https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 命令傳回。

   此外，若 API 在 `us-east-1` 以外的區域，您將需要替代正確的區域。

1. 為了測試您的 API，請在連線的同時輸入如下訊息：

   ```
   {"{jsonpath-expression}":"{route-key}"}
   ```

   其中 *\$1jsonpath-expression\$1* 是一種 JSONPath 表達式和 *\$1route-key\$1* 是 API 的路由金鑰。例如：

   ```
   {"action":"action1"}
   {"message":"test response body"}
   ```

   如需 JSONPath 的詳細資訊，請參閱 [JSONPath](https://goessner.net/articles/JsonPath/) 或[適用於 Java 的 JSONPath](https://github.com/json-path/JsonPath)。

1. 若要中斷與 API 的連線，請輸入 `ctrl-C`。

# 在後端服務使用 `@connections` 命令
<a name="apigateway-how-to-call-websocket-api-connections"></a>

後端服務可以使用以下 WebSocket 連線 HTTP 請求，來將回呼訊息傳送到連線用戶端、取得連線資訊，或中斷用戶端。

**重要**  
這些請求使用 [IAM 授權](apigateway-websocket-control-access-iam.md)，所以您必須使用 [Signature 第 4 版 (SigV4)](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html) 來進行簽署。若要執行此作業，您可以使用 API Gateway 管理 API。如需詳細資訊，請參閱 [ApiGatewayManagementApi](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/apigatewaymanagementapi.html)。

在下列命令中，您需要將 取代`{api-id}`為實際的 API ID，該 ID 會顯示在 API Gateway 主控台中，或由 AWS CLI [createe-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api.html) 命令傳回。使用此命令之前，您必須先建立連線。

若要將回呼訊息傳送給用戶端，請使用：

```
POST https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

您可以使用 `[Postman](https://www.postman.com/)` 或呼叫 `[awscurl](https://github.com/okigan/awscurl)` 來測試此請求，如下範例所示：

```
awscurl --service execute-api -X POST -d "hello world" https://{prefix}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

您需要以 URL 編碼處理命令，如以下範例所示：

```
awscurl --service execute-api -X POST -d "hello world" https://aabbccddee.execute-api.us-east-1.amazonaws.com/prod/%40connections/R0oXAdfD0kwCH6w%3D
```

若要取得用戶端的最新連線狀態，請使用下列命令：

```
GET https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

若要中斷用戶端連線，請使用下列命令：

```
DELETE https://{api-id}.execute-api.us-east-1.amazonaws.com/{stage}/@connections/{connection_id}
```

您可以在整合時使用 `$context` 變數來動態建置回呼 URL。例如，如果您使用 Lambda 代理整合搭配 `Node.js` Lambda 函數，您可以如下所示建置 URL，並傳送訊息到連線用戶端：

```
import {
  ApiGatewayManagementApiClient,
  PostToConnectionCommand,
} from "@aws-sdk/client-apigatewaymanagementapi";

export const handler = async (event) => {
  const domain = event.requestContext.domainName;
  const stage = event.requestContext.stage;
  const connectionId = event.requestContext.connectionId;
  const callbackUrl = `https://${domain}/${stage}`;
  const client = new ApiGatewayManagementApiClient({ endpoint: callbackUrl });

  const requestParams = {
    ConnectionId: connectionId,
    Data: "Hello!",
  };

  const command = new PostToConnectionCommand(requestParams);

  try {
    await client.send(command);
  } catch (error) {
    console.log(error);
  }

  return {
    statusCode: 200,
  };
};
```

如果您使用 WebSocket API 的自訂網域名稱，請從函數程式碼中移除 `stage` 變數。

傳送回呼訊息時，您的 Lambda 函數必須具有呼叫 API Gateway 管理 API 的權限。如果在建立連線前或用戶端中斷連線後張貼訊息，您可能會收到含有 `GoneException` 的錯誤訊息。

# 發布 WebSocket API 以供客戶調用
<a name="websocket-api-publish"></a>

只是建立和開發 API Gateway API，並不代表使用者可以自動呼叫 API。若要使其可供呼叫，您必須將 API 部署到階段。此外，您可能會想要自訂使用者用於存取 API 的 URL。您可以為它提供一個與您品牌一致的網域，或是比 API 預設 URL 更好記的網域。

在本節中，您可以了解如何部署 API，以及如何自訂提供給使用者以存取 API 的 URL。

**注意**  
為了增強 API Gateway API 的安全性，`execute-api.{region}.amazonaws.com` 網域會在[公用尾碼清單 (PSL](https://publicsuffix.org/)) 中註冊。為了加強安全性，如果您需要在 API Gateway API 的預設網域名稱中設定敏感性 Cookie，我們建議您使用具 `__Host-` 前置詞的 Cookie。此做法將有助於保護您的網域免受跨站請求偽造 (CSRF) 攻擊。如需更多資訊，請參閱 Mozilla 開發人員網路中的[設定 Cookie](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) 頁面。

**Topics**
+ [在 API Gateway 中建立 WebSocket API 的各階段](websocket-api-stages.md)
+ [在 API Gateway 中部署 WebSocket API](apigateway-set-up-websocket-deployment.md)
+ [API Gateway 中適用於 WebSocket API 的安全政策](websocket-api-ciphers.md)
+ [API Gateway 中的 WebSocket API 私有 API 的自訂網域名稱](websocket-api-custom-domain-names.md)

# 在 API Gateway 中建立 WebSocket API 的各階段
<a name="websocket-api-stages"></a>

API 階段是 API 生命週期狀態的邏輯參考 (例如，`dev`、`prod`、`beta` 或 `v2`)。API 階段是由其 API ID 及階段名稱來識別，而且它們會包含在您用來呼叫 API 的 URL 中。每個階段都是 API 部署的具名參考，且可供用戶端應用程式呼叫。

部署是 API 組態的快照。將 API 部署到階段之後，用戶端就可以叫用它。您必須部署 API 才能讓變更生效。

## 階段變數
<a name="websocket-api-stages.stage-variables"></a>

階段變數是您可為 WebSocket API 定義階段的索引鍵/值對。它們的作用如同環境變數，而且可用於 API 設定。

例如，您可以定義階段變數，然後將其值設定為 HTTP Proxy 整合的 HTTP 端點。稍後，您可以使用相關聯的階段變數名稱來參照端點。如此，您可以在每個階段使用不同的端點來使用相同的 API 設定。同樣地，您可以使用階段變數，為 API 的每個階段指定不同的 AWS Lambda 函數整合。

**注意**  
階段變數並非用於敏感資料，例如登入資料。若要將敏感資料傳遞至整合，請使用 AWS Lambda 授權方。您可以將敏感資料傳遞至 Lambda 授權方輸出中的整合。如需進一步了解，請參閱[Lambda 授權方回應格式](http-api-lambda-authorizer.md#http-api-lambda-authorizer.payload-format-response)。

### 範例
<a name="websocket-api-stages.stage-variables-examples"></a>

若要使用階段變數來自訂 HTTP 整合端點，您必須先將階段變數 (例如，`url`) 的名稱和值設定為 `example.com`。之後，設定 HTTP 代理整合。您可以告訴 API Gateway 使用階段變數值 **http://\$1\$1stageVariables.url\$1**，而不需要輸入端點的 URL。此值會指示 API Gateway 在執行時間替換您的階段變數 `${}`，視您 API 的階段而定。

您可以使用類似的方式來參考階段變數，以指定 Lambda 函數名稱或 AWS 角色 ARN。

將 Lambda 函數名稱指定為階段變數值時，您必須在 Lambda 函數中手動設定許可。以下 [add-permission](https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html) 命令會新增必要的許可：

```
aws lambda add-permission --function-name arn:aws:lambda:XXXXXX:your-lambda-function-name --source-arn arn:aws:execute-api:us-east-1:YOUR_ACCOUNT_ID:api_id/*/HTTP_METHOD/resource --principal apigateway.amazonaws.com --statement-id apigateway-access --action lambda:InvokeFunction
```

## API Gateway 階段變數參考
<a name="websocket-api-stages.stage-variables-reference"></a>

### HTTP 整合 URI
<a name="websocket-api-stages.stage-variables-in-integration-HTTP-uris"></a>

您可以使用階段變數作為 HTTP 整合 URI 的一部分，如下例範例所示。
+ 不含通訊協定的完整 URI – `http://${stageVariables.<variable_name>}`
+ 完整的網域 – `http://${stageVariables.<variable_name>}/resource/operation`
+ 子網域 – `http://${stageVariables.<variable_name>}.example.com/resource/operation`
+ 路徑 – `http://example.com/${stageVariables.<variable_name>}/bar`
+ 查詢字串 – `http://example.com/foo?q=${stageVariables.<variable_name>}` 

### Lambda 函數
<a name="websocket-api-stages.stage-variables-in-integration-lambda-functions"></a>

 您可以使用階段變數取代 Lambda 函數名稱或別名，如下列範例所示。
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:${stageVariables.<function_variable_name>}/invocations`
+ `arn:aws:apigateway:<region>:lambda:path/2015-03-31/functions/arn:aws:lambda:<region>:<account_id>:function:<function_name>:${stageVariables.<version_variable_name>}/invocations`

**注意**  
若要使用 Lambda 函數的階段變數，函數必須與 API 位於相同的帳戶中。階段變數不支援跨帳戶 Lambda 函數。

### AWS 整合憑證
<a name="websocket-api-stages.stage-variables-in-integration-aws-credentials"></a>

 您可以使用階段變數做為 AWS 使用者或角色登入資料 ARN 的一部分，如下列範例所示。
+  `arn:aws:iam::<account_id>:${stageVariables.<variable_name>}` 

# 在 API Gateway 中部署 WebSocket API
<a name="apigateway-set-up-websocket-deployment"></a>

 建立 WebSocket API 後，您必須將其部署以您的使用者叫用。

若要部署 API，請建立 [API 部署](api-gateway-basic-concept.md#apigateway-definition-api-deployment)，並建立它與[階段](api-gateway-basic-concept.md#apigateway-definition-api-stage)的關聯。每個階段都是 API 的快照，而且可以供用戶端應用程式呼叫。

**重要**  
每次更新 API 時，都必須將其重新部署。對階段設定以外的任何變更都需要重新部署，對下列資源進行修改時也是如此：  
路由
整合
授權方
在預設情況下，每個 API 只能有 10 個階段。建議您針對部署重複使用這些階段。

若要呼叫已部署的 WebSocket API，用戶端會將訊息傳送到 API 的 URL。URL 的決定方式為 API 的主機名稱和階段名稱。

**注意**  
API Gateway 將支援高達 128 KB 的承載，影格大小上限為 32 KB。如果訊息超過 32 KB，則必須分割成多個影格，每個為 32 KB 或以下。

使用 API 的預設網域名稱，處於指定階段 (`{stageName}`) 的 (例如) WebSocket API URL 格式如下：

```
wss://{api-id}.execute-api.{region}.amazonaws.com/{stageName}
```

為了讓使用者更容易使用 WebSocket API 的 URL，您可以建立自訂網域名稱 (例如，`api.example.com`) 以取代 API 的預設主機名稱。其組態程序與 REST API 相同。如需更多詳細資訊，請參閱 [API Gateway 中公有 REST API 的自訂網域名稱](how-to-custom-domains.md)。

階段啟用 API 的強大版本控制。例如，您可以將 API 部署至 `test` 階段和 `prod` 階段，並使用 `test` 階段作為測試組建，以及使用 `prod` 階段作為穩定組建。更新通過測試之後，您就可以將 `test` 階段提升為 `prod` 階段。您可以將 API 重新部署到 `prod` 階段來進行提升。如需階段的詳細資訊，請參閱 [在 API Gateway 中為 REST API 設定階段](set-up-stages.md)。

**Topics**
+ [使用 建立 WebSocket API 部署 AWS CLI](#apigateway-create-websocket-deployment-using-awscli)
+ [使用 API Gateway 主控台建立 WebSocket API 部署](#apigateway-create-websocket-deployment-using-console)

## 使用 建立 WebSocket API 部署 AWS CLI
<a name="apigateway-create-websocket-deployment-using-awscli"></a>

下列 [create-deployment](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-deployment.html) 命令會建立部署：

```
aws apigatewayv2 --region us-east-1 create-deployment --api-id aabbccddee
```

輸出將如下所示：

```
{
    "DeploymentId": "fedcba",
    "DeploymentStatus": "DEPLOYED",
    "CreatedDate": "2018-11-15T06:49:09Z"
}
```

在您將此部署與階段建立關聯前，都無法呼叫已部署的 API。您可以建立新階段或重複使用您之前建立的階段。

以下 [create-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-stage.html) 命令會建立一個新階段，並將其與部署建立關聯：

```
aws apigatewayv2 --region us-east-1 create-stage --api-id aabbccddee --deployment-id fedcba --stage-name test
```

輸出看起來如下：

```
{
    "StageName": "test",
    "CreatedDate": "2018-11-15T06:50:28Z",
    "DeploymentId": "fedcba",
    "DefaultRouteSettings": {
        "MetricsEnabled": false,
        "ThrottlingBurstLimit": 5000,
        "DataTraceEnabled": false,
        "ThrottlingRateLimit": 10000.0
    },
    "LastUpdatedDate": "2018-11-15T06:50:28Z",
    "StageVariables": {},
    "RouteSettings": {}
}
```

您也可以使用新建立的部署 ID (*deployment-id*) 來更新階段的 `deploymentId` 屬性，以重複使用現有階段。以下 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) 命令會更新階段的部署 ID：

```
aws apigatewayv2 update-stage --region region \
    --api-id api-id \ 
    --stage-name stage-name \ 
    --deployment-id deployment-id
```

## 使用 API Gateway 主控台建立 WebSocket API 部署
<a name="apigateway-create-websocket-deployment-using-console"></a>

若要使用 API Gateway 主控台為 WebSocket API 建立部署：

1. 登入 API Gateway 主控台並選擇 API。

1. 選擇**部署 API**。

1. 從下拉式清單中選擇所需的階段，或輸入新階段的名稱。

# API Gateway 中適用於 WebSocket API 的安全政策
<a name="websocket-api-ciphers"></a>

API Gateway 會針對所有 WebSocket API 端點強制執行 `TLS_1_2` 的安全政策。

*安全政策*是由 Amazon API Gateway 提供的最低 TLS 版本與密碼套件的預先定義組合。TLS 通訊協定可解決用戶端和伺服器間的竄改與竊聽等網路安全問題。當用戶端透過自訂網域建立 API 的 TLS 信號交換時，安全政策會強制執行用戶端可選擇使用的 TLS 版本和密碼套件。此安全政策接受 TLS 1.2 和 TLS 1.3 流量，並拒絕 TLS 1.0 流量。

## WebSocket API 支援的 TLS 通訊協定和密碼
<a name="websocket-api-custom-domain-ciphers-list"></a>

下表說明 WebSocket API 支援的 TLS 通訊協定。


| **TLS 通訊協定** | **TLS\$11\$12 安全政策** | 
| --- | --- | 
| TLSv1.3 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLSv1.2 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 

下表說明適用於 WebSocket API 的 TLS 1\$12 安全政策的 TLS 加密。


| **TLS 加密** | **TLS\$11\$12 安全政策** | 
| --- | --- | 
| TLS\$1AES\$1128\$1GCM\$1SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLS\$1AES\$1256\$1GCM\$1SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| TLS\$1CHACHA20\$1POLY1305\$1SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-ECDSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| ECDHE-RSA-AES256-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES128-GCM-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES128-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES256-GCM-SHA384 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 
| AES256-SHA256 | ![\[alt text not found\]](http://docs.aws.amazon.com/zh_tw/apigateway/latest/developerguide/images/success_icon.svg) 是 | 

## OpenSSL 和 RFC 密碼名稱
<a name="apigateway-secure-connections-openssl-rfc-cipher-names-websocket"></a>

OpenSSL 和 IETF RFC 5246 使用相同密碼的不同名稱。如需密碼名稱的清單，請參閱 [OpenSSL 和 RFC 密碼名稱](apigateway-security-policies-list.md#apigateway-secure-connections-openssl-rfc-cipher-names)。

## REST API 和 HTTP API 的相關資訊
<a name="apigateway-websocket-additional-apis"></a>

如需 REST API 和 HTTP API 的詳細資訊，請參閱 [在 API Gateway 中為您的自訂網域選擇安全政策](apigateway-custom-domain-tls-version.md) 和 [API Gateway 中 HTTP API 的安全政策](http-api-ciphers.md)。

# API Gateway 中的 WebSocket API 私有 API 的自訂網域名稱
<a name="websocket-api-custom-domain-names"></a>

*自訂網域名稱*是更簡單且更直觀的 URL，可提供給 API 使用者。

部署 API 之後，您 (和您的客戶) 可以使用下列格式的預設基本 URL 來呼叫 API：

```
https://api-id.execute-api.region.amazonaws.com/stage
```

其中 *api-id* 是 API Gateway 所產生，*region* 即為 (AWS 區域)，而 *stage* 是您在部署 API 時所指定。

URL 的主機名稱部分 (即 `api-id.execute-api.region.amazonaws.com`) 指的是 API 端點。預設 API 端點是隨機產生的，不容易取回，而且不方便使用。

使用自訂網域名稱，您就能設定 API 的主機名稱，並選擇基本路徑 (例如，`myservice`) 將替代 URL 映射至您的 API。例如，更方便使用者使用的 API 基本 URL 可以成為：

```
https://api.example.com/myservice
```

## 考量事項
<a name="websocket-api-custom-domain-names-considerations"></a>

下列考量事項可能會影響您使用自訂網域名稱。
+ 如果您將自訂網域名稱映射至 WebSocket API，則無法映射至 REST API 或 HTTP API。
+ 僅支援區域性自訂網域名稱。
+ 對於最低 TLS 版本，僅 TLS 1.2 受支援。
+ 您必須建立或更新 DNS 提供者的資源記錄，以映射至您的 API 端點。如果沒有這種映射，送往自訂網域名稱的 API 請求無法到達 API Gateway。
+ 您可以使用萬用字元憑證來支援幾乎不限數量的網域名稱，而不會超過預設配額。如需更多詳細資訊，請參閱 [萬用字元自訂網域名稱](http-api-custom-domain-names.md#http-wildcard-custom-domain-names)。

## 先決條件
<a name="websocket-api-custom-domain-names-prerequisites"></a>

以下是自訂網域名稱的先決條件。

### 註冊網域名稱
<a name="websocket-api-custom-domain-names-register"></a>

您必須具有已註冊的網際網路網域名稱，才能為您的 API 設定自訂網域名稱。您可以使用 [Amazon Route 53](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/) 或使用您選擇的第三方網域註冊機構來註冊網際網路網域。您的自訂網域名稱可以是已註冊網際網路網域的子網域或根網域 (也稱為 "zone apex") 的名稱。

您的網域名稱必須遵循 [RFC 1035](https://tools.ietf.org/html/rfc1035#section-2.3.4) 規格，每個標籤最多可有 63 個八位元組，總共有 255 個八位元組。

### 自訂網域名稱的憑證
<a name="websocket-api-custom-domain-names-certificates"></a>

必須為 API 設定自訂網域名稱前，您必須先在 ACM 中備妥 SSL/TLS 憑證。如果您建立自訂網域名稱的 AWS 區域中無法使用 ACM，則必須將憑證匯入該區域中的 API Gateway。

若要匯入 SSL/TLS 憑證，您必須提供 PEM 格式化 SSL/TLS 憑證內文、私有金鑰，以及自訂網域名稱的憑證鏈。

ACM 中所存放的每個憑證都是透過其 ARN 進行識別。使用 ACM 所發出的憑證，就不需要擔心公開任何敏感的憑證詳細資訊，例如私有金鑰。若要使用網域名稱的 AWS 受管憑證，您只需要參考其 ARN。

如果您的應用程式是使用憑證關聯 (有時稱為 SSL 關聯) 來關聯 ACM 憑證，則 AWS 續約憑證後，應用程式可能會無法連線到您的網域。如需詳細資訊，請參閱 *AWS Certificate Manager 使用者指南*中的[憑證關聯問題](https://docs.aws.amazon.com/acm/latest/userguide/troubleshooting-pinning.html)。

## 萬用字元自訂網域名稱
<a name="websocket-api-wildcard-custom-domain-names"></a>

使用萬用字元自訂網域名稱，您可以支援幾乎無限數目的網域名稱，而不會超過[預設配額](limits.md)。例如，您可以為每個客戶提供其自己的網域名稱，`customername.api.example.com`。

若要建立萬用字元自訂網域名稱，可以指定萬用字元 (`*`) 作為自訂網域的第一個子網域，藉以表示根網域所有可能的子網域。

例如，萬用字元自訂網域名稱 `*.example.com` 會產生如 `a.example.com`、`b.example.com` 和 `c.example.com` 等子網域，而這些子網域全都路由至相同的網域。

萬用字元自訂網域名稱支援來自 API Gateway 標準自訂網域名稱的相異組態。例如，您可以在單一 AWS 帳戶中，設定 `*.example.com` 和 `a.example.com` 採取不同的行為。

您可以使用 `$context.domainName` 和 `$context.domainPrefix` 內容變數來判斷用戶端用來呼叫 API 的網域名稱。若要進一步了解環境變數，請參閱 [用於 API Gateway 資料轉換的變數](api-gateway-mapping-template-reference.md)。

若要建立萬用字元自訂網域名稱，您必須提供由 ACM 發行並已經使用 DNS 或電子郵件驗證方法驗證的憑證。

**注意**  
如果不同的 AWS 帳戶已建立與萬用字元自訂網域名稱衝突的自訂網域名稱，則您無法建立萬用字元自訂網域名稱。例如，如果帳戶 A 已建立 `a.example.com`，則帳戶 B 無法建立萬用字元自訂網域名稱 `*.example.com`。  
如果帳戶 A 和帳戶 B 共用擁有者，您可以聯絡 [AWS 支援中心](https://console.aws.amazon.com/support/home#/)，以請求例外狀況。

## 自訂網域名稱的後續步驟
<a name="websocket-api-custom-domain-names-next-steps"></a>

若要設定 HTTP API 的自訂網域名稱，請參閱《API Gateway 開發人員指南》中的 REST API 相關章節文件。

首先，指定自訂網域名稱所用的憑證。如需更多詳細資訊，請參閱 [在 中備妥憑證 AWS Certificate Manager](how-to-specify-certificate-for-custom-domain-name.md)。接著，建立區域性自訂網域名稱。如需更多詳細資訊，請參閱 [在 API Gateway 中設定區域性自訂網域名稱](apigateway-regional-api-custom-domain-create.md)。

# 將 API 階段映射至 WebSocket API 的自訂網域名稱
<a name="websocket-api-mappings"></a>

您可以使用 API 映射將 API 階段連線至自訂網域名稱。建立網域名稱並設定 DNS 記錄之後，您可以使用 API 映射，透過自訂網域名稱將流量傳送至您的 API。

API 映射指定一個 API，一個階段，以及選擇性用於映射的路徑。例如，您可以將 API 的 `production` 階段映射至 `wss://api.example.com/orders`。

建立 API 映射之前，您必須先擁有 API、階段和自訂網域名稱。如需進一步了解如何建立自訂網域名稱，請參閱[在 API Gateway 中設定區域性自訂網域名稱](apigateway-regional-api-custom-domain-create.md)。

## 限制
<a name="websocket-api-mappings-restrictions"></a>
+ 在 API 映射中，自訂網域名稱和映射的 API 必須位於同一個 AWS 帳戶中。
+ API 映射只能包含字母、數字和下列字元：`$-_.+!*'()`。
+ API 映射中路徑的最大長度為 300 個字元。
+ 您無法將 WebSocket API 映射至與 HTTP API 或 REST API 相同的自訂網域名稱。
+ 如果您建立具有多層的 API 映射，API Gateway 會將所有標頭名稱轉換為小寫。

## 建立 API 映射
<a name="websocket-api-mappings-examples"></a>

若要建立 API 映射，您必須先建立自訂網域名稱、API 和階段。如需建立自訂網域名稱的資訊，請參閱[在 API Gateway 中設定區域性自訂網域名稱](apigateway-regional-api-custom-domain-create.md)。

------
#### [ AWS 管理主控台 ]

**建立 API 映射**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇 **Custom domain names** (自訂網域名稱)。

1. 選取您已建立的自訂網域名稱。

1. 選擇 **API mappings** (API 映射)。

1. 選擇 **Configure API mappings (設定 API 映射)**。

1. 選擇 **Add new mapping (新增映射)**。

1. 輸入 **API**、**Stage** (階段)，以及選擇性地輸入 **Path** (路徑)。

1. 選擇**儲存**。

------
#### [ AWS CLI ]

以下 [create-api-mapping](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-api-mapping.html) 命令會建立 API 映射。在此範例中，API Gateway 會將請求傳送至 `api.example.com/v1`，到指定的 API 和階段。

```
aws apigatewayv2 create-api-mapping \
    --domain-name api.example.com \
    --api-mapping-key v1 \
    --api-id a1b2c3d4 \
    --stage test
```

------
#### [ CloudFormation ]

以下 CloudFormation 範例會建立 API 映射。

```
MyApiMapping:
  Type: 'AWS::ApiGatewayV2::ApiMapping'
  Properties:
    DomainName: api.example.com
    ApiMappingKey: 'v1'
    ApiId: !Ref MyApi
    Stage: !Ref MyStage
```

------

# WebSocket API 自訂網域名稱的 IP 位址類型
<a name="websocket-api-custom-domain-names-ip-address-type"></a>

建立自訂網域名稱時，您可以指定可調用網域的 IP 位址類型。您可以選擇 IPv4 來解析 IPv4 位址以調用網域，也可以選擇雙堆疊，以同時允許 IPv4 和 IPv6 位址調用您的網域。我們建議您將 IP 位址類型設定為雙堆疊，以緩解 IP 空間耗盡或用於安全狀態。如需雙堆疊 IP 位址類型優點的詳細資訊，請參閱 [AWS 上的 IPv6](https://docs.aws.amazon.com/whitepapers/latest/ipv6-on-aws/internet-protocol-version-6.html)。

## IP 位址類型的考量事項
<a name="websocket-api-custom-domain-names-ip-address-type-considerations"></a>

下列考量事項可能會影響您使用 IP 位址類型。
+ API Gateway 自訂網域名稱的預設 IP 位址類型為 IPv4。
+ 您的自訂網域名稱不需要針對所有與其對應的 API 使用相同 IP 位址類型。如果您停用預設 API 端點，則可能會影響呼叫方調用 API 的方式。

## 變更自訂網域名稱的 IP 位址類型
<a name="websocket-api-custom-domain-names-ip-address-type-change"></a>

您可以藉由更新網域名稱的端點組態來變更 IP 位址類型。您可以使用 AWS 管理主控台、AWS CLI、CloudFormation 或 AWS SDK 來更新端點組態。

------
#### [ AWS 管理主控台 ]

**若要變更自訂網域名稱的 IP 位址類型**

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇公有自訂網域名稱。

1. 選擇**端點組態**。

1. 針對 IP 位址類型，選取 **IPv4** 或**雙堆疊**。

1. 選擇**儲存**。

------
#### [ AWS CLI ]

以下 [update-domain-name](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-domain-name.html) 命令會將 API 更新為雙堆疊 IP 位址類型：

```
aws apigatewayv2 update-domain-name \
   --domain-name dualstack.example.com \
   --domain-name-configurations CertificateArn=arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc,IpAddressType=dualstack
```

輸出將如下所示：

```
{
    "ApiMappingSelectionExpression": "$request.basepath",
    "DomainName": "dualstack.example.com",
    "DomainNameConfigurations": [
        {
            "ApiGatewayDomainName": "d-abcd1234.execute-api.us-east-1.amazonaws.com",
            "CertificateArn": "arn:aws:acm:us-east-1:111122223333:certificate/abcd1234-5678-abc",
            "DomainNameStatus": "AVAILABLE",
            "EndpointType": "REGIONAL",
            "HostedZoneId": "Z3LQWSYCGH4ADY",
            "SecurityPolicy": "TLS_1_2",
            "IpAddressType": "dualstack"
        }
    ],
    "Tags": {}
}
```

------

# 停用 WebSocket API 的預設端點
<a name="websocket-api-disable-default-endpoint"></a>

預設情況下，用戶端可以使用 API Gateway 為 API 產生的 `execute-api` 端點來調用 API。若要確保用戶端只能使用自訂網域名稱來存取您的 API，請停用預設 `execute-api` 端點。當您停用預設端點時，它會影響 API 的所有階段。

下列程序顯示如何停用 WebSocket API 的預設端點。

------
#### [ AWS 管理主控台 ]

1. 在以下網址登入 API Gateway 主控台：[https://console.aws.amazon.com/apigateway](https://console.aws.amazon.com/apigateway)。

1. 選擇 WebSocket API。

1. 選擇 **API 設定**。

1. 在 **API 詳細資訊**上，選擇**編輯**。

1. 針對**預設端點**，選取**非作用中**。

1. 選擇**儲存變更**。

1. 在主要導覽窗格中，選擇**路由**。

1. 選擇**部署**，然後重新部署您的 API 或建立新的階段，以使變更生效。

------
#### [ AWS CLI ]

以下 [update-api](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-api.html) 命令會停用 WebSocket API 的預設端點：

```
aws apigatewayv2 update-api \
    --api-id abcdef123 \
    --disable-execute-api-endpoint
```

停用預設端點之後，您必須部署 API，變更才會生效。

下列 AWS CLI 命令會建立部署。

```
aws apigatewayv2 create-deployment \
    --api-id abcdef123 \
    --stage-name dev
```

------

# 在 API Gateway 中保護您的 WebSocket API
<a name="websocket-api-protect"></a>

API Gateway 提供多種方法來保護 API 免於遭受特定威脅，例如惡意使用者或流量高峰。您可以使用產生 SSL 憑證或設定限流目標等策略來保護 API。如需產生 SSL 憑證的詳細資訊，請參閱 [在 API Gateway 中產生和設定後端驗證的 SSL 憑證](getting-started-client-side-ssl-authentication.md)。本節其餘部分涵蓋設定限流目標。

您可以為您的 API 設定調節，以防止 API 接收過多請求。調節會依最佳作法來套用，它們都應該視為目標，而非確定的請求上限。

API Gateway 會使用字符儲存貯體演算法將字符計算為請求，進而調節傳送給 API 的請求量。具體而言，API Gateway 會按區域檢查帳戶中所有 API 的速率和爆量請求次數。在字符儲存貯體演算法中，爆量可以實現預先定義的超限，但在某些情況下，其他因素也可能導致超限。

提交的請求量超出穩定狀態請求率和爆量限制時，API Gateway 會開始調節請求量。此時用戶端可能會收到 `429 Too Many Requests` 的錯誤回應。發現這類例外狀況時，用戶端可以採用限制速率的方式來重新提交失敗的請求。

身為 API 開發人員，您可以設定個別 API 階段或路由的目標限制，來改善您帳戶中所有 API 的整體效能。

## 每個區域的帳戶層級調節
<a name="websocket-api-protect-throttling-account"></a>

預設情況下，API Gateway 會按區域限制 AWS 帳戶內所有 API 的每秒穩定狀態請求量 (RPS)。它還會按區域限制 AWS 帳戶內所有 API 的爆量 (即儲存貯體大小上限)。在 API Gateway 中，爆量限制代表 API Gateway 傳回 `429 Too Many Requests` 錯誤回應前可實現的並行請求提交數上限。如需有關調節配額的詳細資訊，請參閱 [Amazon API Gateway 配額](limits.md)。

帳戶型限制會套用至指定區域內某帳戶的所有 API。帳戶層級速率限制可按請求提高。使用較短逾時值和較小酬載的 API 可擁有更高的上限。如需請求提高區域內帳戶層級的調節限制，請與 [AWS 支援中心](https://console.aws.amazon.com/support/home#/)聯絡。如需詳細資訊，請參閱[Amazon API Gateway 配額](limits.md)。請注意，這些限制不能高於限 AWS 流限制。

## 路由層級調節
<a name="websocket-api-protect-throttling-route"></a>

您可以設定路由層級調節，來覆寫特定階段或 API 中個別路由的帳戶層級請求調節限制。預設路由調節限制不能超出帳戶層級速率限制。

您可以使用 AWS CLI設定路由層級的節流設定。以下 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) 命令會針對指定的 API 階段和路由設定自訂限流：

```
aws apigatewayv2 update-stage \
    --api-id a1b2c3d4 \
    --stage-name dev \
    --route-settings '{"messages":{"ThrottlingBurstLimit":100,"ThrottlingRateLimit":2000}}'
```

# 在 API Gateway 中監控的 WebSocket API
<a name="websocket-api-monitor"></a>

您可以使用 CloudWatch 指標和 CloudWatch Logs 來監控 WebSocket API。藉由結合日誌和指標，您可以記錄錯誤並監控 API 的效能。

**注意**  
在下列情況下，API Gateway 可能無法產生日誌和指標：  
413 請求實體過大錯誤
過多的 429 請求過多錯誤
400 系列錯誤，來自傳送至沒有 API 映射自訂網域的要求
由於內部失敗造成的 500 系列錯誤

**Topics**
+ [使用 CloudWatch 指標監控 WebSocket API 執行](apigateway-websocket-api-logging.md)
+ [在 API Gateway 中設定 WebSocket API 的記錄](websocket-api-logging.md)

# 使用 CloudWatch 指標監控 WebSocket API 執行
<a name="apigateway-websocket-api-logging"></a>

您可以使用 [Amazon CloudWatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html) 指標來監控 WebSocket API。該組態與用於 REST API 的組態類似。如需更多詳細資訊，請參閱 [使用 Amazon CloudWatch 指標監控 REST API 執行](monitoring-cloudwatch.md)。

WebSocket API 支援以下指標：


| 指標 | 描述 | 
| --- | --- | 
| ConnectCount | 傳送到 \$1connect 路由整合的訊息數。 | 
| MessageCount | 傳送到 WebSocket API 的訊息數 (來自用戶端或傳送到用戶端)。 | 
| IntegrationError | 從整合傳回 4XX/5XX 回應的請求數。 | 
| ClientError | 擁有在整合受到叫用前由 API Gateway 傳回的 4XX 回應之請求數。 | 
| ExecutionError | 呼叫整合時發生的錯誤。 | 
| IntegrationLatency | API Gateway 將請求傳送至整合與 API Gateway 從整合接收回應之間的時間差異。受回呼和偽裝整合抑制。 | 

您可以使用下表中的維度來篩選 API Gateway 指標。


| 維度 | 描述 | 
| --- | --- | 
| ApiId | 篩選具指定 API ID 之 API 的 API Gateway 指標。 | 
| ApiId、階段 | 篩選具指定 API ID 與階段 ID 之 API 階段的 API Gateway 指標。 | 
| ApiId、方法、資源、階段 |  篩選具指定 API ID、階段 ID、資源路徑和路由 ID 之 API 方法的 API Gateway 指標。 除非您已明確啟用詳細的 CloudWatch 指標，否則 API Gateway 不會傳送這類指標。您可以透過呼叫 API Gateway V2 REST API 的 [UpdateStage](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-stages-stagename.html) 動作，將 `detailedMetricsEnabled` 屬性更新為 `true`。或者，您可以呼叫 [update-stage](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/update-stage.html) AWS CLI 命令，將 `DetailedMetricsEnabled` 屬性更新為 `true`。啟用這類指標會產生您帳戶的額外費用。如需定價資訊，請參閱 [Amazon CloudWatch 定價](https://aws.amazon.com/cloudwatch/pricing/)。  | 

# 在 API Gateway 中設定 WebSocket API 的記錄
<a name="websocket-api-logging"></a>

您可以啟用記錄功能，將日誌寫入 CloudWatch Logs。CloudWatch 有兩種類型的 API 記錄：執行記錄和存取記錄。在執行記錄中，API Gateway 會管理 CloudWatch Logs。此程序包含建立日誌群組和日誌串流，以及向日誌串流報告任何發起人的請求和回應。

若要提升您的安全狀態，建議您在 `ERROR` 或 `INFO` 層級使用執行記錄。您可能需要這樣做，才能符合各種合規架構。如需詳細資訊，請參閱《AWS Security Hub 使用者指南》**中的 [Amazon API Gateway 控制項](https://docs.aws.amazon.com/securityhub/latest/userguide/apigateway-controls.html)。

在存取記錄中，您身為 API 開發人員且想要記錄誰已存取您的 API 以及發起人存取 API 的方式。您可以建立自己的日誌群組，或選擇由 API Gateway 管理的現有日誌群組。若要指定存取權詳細資料，您可以選取 `$context` 變數 (以所選擇格式表示)，以及選擇日誌群組作為目標。

如需有關如何設定 CloudWatch 記錄功能的指示，請參閱[使用 API Gateway 主控台設定 CloudWatch API 記錄功能](set-up-logging.md#set-up-access-logging-using-console)。

當您指定 **Log Format (日誌格式)**，您可以選擇要記錄哪些環境變數。支援下列變數。


| 參數 | 描述 | 
| --- | --- | 
| \$1context.apiId |  API Gateway 指派給您 API 的識別碼。  | 
| \$1context.authorize.error | 授權錯誤訊息。 | 
| \$1context.authorize.latency | 授權延遲 (以毫秒為單位)。 | 
| \$1context.authorize.status | 從授權嘗試傳回的狀態碼。 | 
| \$1context.authorizer.error | 從授權方傳回的錯誤訊息。 | 
| \$1context.authorizer.integrationLatency | Lambda 授權方延遲 (以毫秒為單位)。 | 
| \$1context.authorizer.integrationStatus | 從 Lambda 授權方傳回的狀態碼。 | 
| \$1context.authorizer.latency | 授權方延遲 (以毫秒為單位)。 | 
| \$1context.authorizer.requestId |  AWS 端點的請求 ID。 | 
| \$1context.authorizer.status | 從授權方傳回的狀態碼。 | 
| \$1context.authorizer.principalId |  與用戶端所傳送並從 API Gateway Lambda 授權方 Lambda 函數所傳回之權杖建立關聯的主要使用者識別。(Lambda 授權方之前稱為自訂授權方。)  | 
| \$1context.authorizer.property |  API Gateway Lambda 授權方函數所傳回 `context` 映射之指定索引鍵/值組的字串化值。例如，如果授權方傳回下列 `context` 映射： <pre>"context" : {<br />                            "key": "value",<br />                            "numKey": 1,<br />                            "boolKey": true<br />                            }</pre> 呼叫 `$context.authorizer.key` 會傳回 `"value"` 字串、呼叫 `$context.authorizer.numKey` 會傳回 `"1"` 字串，而呼叫 `$context.authorizer.boolKey` 會傳回 `"true"` 字串。  | 
| \$1context.authenticate.error | 從驗證嘗試傳回的錯誤訊息。 | 
| \$1context.authenticate.latency | 驗證延遲 (以毫秒為單位)。 | 
| \$1context.authenticate.status | 從驗證嘗試傳回的狀態碼。 | 
| \$1context.connectedAt |  [Epoch](https://en.wikipedia.org/wiki/Unix_time) 格式化連線時間。  | 
| \$1context.connectionId |  連線的唯一 ID，可用來回呼用戶端。  | 
| \$1context.domainName |  WebSocket API 的網域名稱。此可用於回呼用戶端 (非硬式編碼的值)。  | 
| \$1context.error.message |  包含 API Gateway 錯誤訊息的字串。  | 
| \$1context.error.messageString | \$1context.error.message 的引用值，即 "\$1context.error.message"。 | 
| \$1context.error.responseType |  錯誤回應類型。  | 
| \$1context.error.validationErrorString |  包含詳細驗證錯誤訊息的字串。  | 
| \$1context.eventType |  事件類型：`CONNECT`、`MESSAGE` 或 `DISCONNECT`。  | 
| \$1context.extendedRequestId | 等同於 \$1context.requestId。 | 
| \$1context.identity.accountId |  與請求相關聯的 AWS 帳戶 ID。  | 
| \$1context.identity.apiKey |  與啟用金鑰之 API 請求建立關聯的 API 擁有者金鑰。  | 
| \$1context.identity.apiKeyId | 與啟用金鑰之 API 請求建立關聯的 API 金鑰 ID。 | 
| \$1context.identity.caller |  已簽署請求之發起人的主體識別符。支援使用 IAM 授權的路由。  | 
| \$1context.identity.cognitoAuthenticationProvider |  提出請求的發起人所使用的所有 Amazon Cognito 驗證提供者清單 (以逗號分隔)。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。 例如，適用於 Amazon Cognito 使用者集區的身分，`cognito-idp. region.amazonaws.com/user_pool_id,cognito-idp.region.amazonaws.com/user_pool_id:CognitoSignIn:token subject claim` 如需有關 Amazon Cognito 驗證提供者的詳細資訊，請參閱《[Amazon Cognito 開發人員指南](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html)》中的*使用聯合身分*。 | 
| \$1context.identity.cognitoAuthenticationType |  提出請求的發起人的 Amazon Cognito 驗證類型。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。可能的值包括用於已驗證身分的 `authenticated` 和未經驗證身分的 `unauthenticated`。 | 
| \$1context.identity.cognitoIdentityId |  提出請求的發起人的 Amazon Cognito 身分 ID。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。  | 
| \$1context.identity.cognitoIdentityPoolId |  提出請求的發起人的 Amazon Cognito 身分集區 ID。僅在使用 Amazon Cognito 登入資料簽署請求時才可使用。  | 
| \$1context.identity.principalOrgId |  [AWS 組織 ID](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_org_details.html)。支援使用 IAM 授權的路由。  | 
| \$1context.identity.sourceIp |  對 API Gateway 提出請求之 TCP 連線的來源 IP 地址。  | 
| \$1context.identity.user |  將針對資源存取授權之使用者的主體識別符。支援使用 IAM 授權的路由。  | 
| \$1context.identity.userAgent |  API 發起人的使用者代理程式。  | 
| \$1context.identity.userArn |  身分驗證之後識別之有效使用者的 Amazon Resource Name (ARN)。  | 
| \$1context.integration.error | 從整合傳回的錯誤訊息。 | 
| \$1context.integration.integrationStatus | 對於 Lambda 代理整合，從 傳回的狀態碼 AWS Lambda，而不是從後端 Lambda 函數程式碼傳回的狀態碼。 | 
| \$1context.integration.latency | 整合延遲 (以毫秒為單位)。等同於 \$1context.integrationLatency。 | 
| \$1context.integration.requestId |  AWS 端點的請求 ID。等同於 \$1context.awsEndpointRequestId。 | 
| \$1context.integration.status | 從整合傳回的狀態碼。對於 Lambda 代理整合而言，這是您的 Lambda 函數程式碼傳回的狀態碼。等同於 \$1context.integrationStatus。 | 
| \$1context.integrationLatency | 毫秒的整合延遲僅可用於存取記錄。 | 
| \$1context.messageId |  訊息的伺服器端唯一 ID。僅在 `$context.eventType` 為 `MESSAGE` 時可用。  | 
| \$1context.requestId |  與 `$context.extendedRequestId` 相同。  | 
| \$1context.requestTime | [CLF](https://httpd.apache.org/docs/current/logs.html#common) 格式化請求時間 (dd/MMM/yyyy:HH:mm:ss \$1-hhmm)。 | 
| \$1context.requestTimeEpoch | [Epoch](https://en.wikipedia.org/wiki/Unix_time) 格式化的要求時間，以毫秒為單位。 | 
| \$1context.routeKey |  所選路由金鑰。  | 
| \$1context.stage |  API 呼叫的部署階段 (例如，Beta 或 Prod)。  | 
| \$1context.status |  回應狀態。  | 
| \$1context.waf.error | 從 傳回的錯誤訊息 AWS WAF。 | 
| \$1context.waf.latency | 以毫秒為單位的 AWS WAF 延遲。 | 
| \$1context.waf.status | 從 傳回的狀態碼 AWS WAF。 | 

一些常用存取日誌格式範例會顯示在 API Gateway 主控台中，並列出如下。
+ `CLF` ([通用日誌格式](https://httpd.apache.org/docs/current/logs.html#common))：

  ```
  $context.identity.sourceIp $context.identity.caller \
  $context.identity.user [$context.requestTime] "$context.eventType $context.routeKey $context.connectionId" \
  $context.status $context.requestId
  ```

  延續字符 (`\`) 代表作為一種視覺輔助。記錄格式必須是單行。您可以在記錄格式的結尾新增新行字元 (`\n`)，以便在每個記錄項目的結尾加入新行。
+  `JSON`: 

  ```
  {
  "requestId":"$context.requestId", \
  "ip": "$context.identity.sourceIp", \
  "caller":"$context.identity.caller", \
  "user":"$context.identity.user", \
  "requestTime":"$context.requestTime", \
  "eventType":"$context.eventType", \
  "routeKey":"$context.routeKey", \
  "status":"$context.status", \
  "connectionId":"$context.connectionId"
  }
  ```

  延續字符 (`\`) 代表作為一種視覺輔助。記錄格式必須是單行。您可以在記錄格式的結尾新增新行字元 (`\n`)，以便在每個記錄項目的結尾加入新行。
+ `XML`: 

  ```
  <request id="$context.requestId"> \
   <ip>$context.identity.sourceIp</ip> \
   <caller>$context.identity.caller</caller> \
   <user>$context.identity.user</user> \
   <requestTime>$context.requestTime</requestTime> \
   <eventType>$context.eventType</eventType> \
   <routeKey>$context.routeKey</routeKey> \
   <status>$context.status</status> \
   <connectionId>$context.connectionId</connectionId> \
  </request>
  ```

  延續字符 (`\`) 代表作為一種視覺輔助。記錄格式必須是單行。您可以在記錄格式的結尾新增新行字元 (`\n`)，以便在每個記錄項目的結尾加入新行。
+ `CSV` (逗號分隔值)：

  ```
  $context.identity.sourceIp,$context.identity.caller, \
  $context.identity.user,$context.requestTime,$context.eventType, \
  $context.routeKey,$context.connectionId,$context.status, \
  $context.requestId
  ```

  延續字符 (`\`) 代表作為一種視覺輔助。記錄格式必須是單行。您可以在記錄格式的結尾新增新行字元 (`\n`)，以便在每個記錄項目的結尾加入新行。