

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

# 在 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` 的錯誤訊息。