

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

# 使用請求和回應
<a name="lambda-generating-http-responses"></a>

若要使用 Lambda@Edge 請求和回應，請參閱下列主題：

**Topics**
+ [使用 Lambda@Edge 函數搭配原始伺服器容錯移轉](#lambda-and-origin-failover)
+ [在請求觸發條件中產生 HTTP 回應](#lambda-generating-http-responses-in-requests)
+ [在原始伺服器回應觸發條件中更新 HTTP 回應](#lambda-updating-http-responses)
+ [選擇包含本文選項來存取請求本文](#lambda-include-body-access)

## 使用 Lambda@Edge 函數搭配原始伺服器容錯移轉
<a name="lambda-and-origin-failover"></a>

您可以使用 Lambda@Edge 函數，與您已使用原始伺服器群組來設定的 CloudFront 分佈搭配，例如，針對您設定來確保高可用性的原始伺服器容錯移轉。若要使用 Lambda 函數與原始伺服器群組搭配，請在您建立快取行為時針對原始伺服器群組觸發的原始伺服器請求或原始伺服器回應中指定函數。

如需詳細資訊，請參閱下列內容：
+ **建立原始伺服器群組：**[建立原始伺服器群組](high_availability_origin_failover.md#concept_origin_groups.creating)
+ **原始伺服器容錯移轉如何使用 Lambda@Edge：**[使用原始伺服器容錯移轉與 Lambda@Edge 函數搭配](high_availability_origin_failover.md#concept_origin_groups.lambda)

## 在請求觸發條件中產生 HTTP 回應
<a name="lambda-generating-http-responses-in-requests"></a>

當 CloudFront 收到請求時，您可以使用 Lambda 函數產生 CloudFront 無需轉送回應給原始伺服器，可直接傳回給檢視器的 HTTP 回應。產生 HTTP 回應降低原始伺服器的負載，且通常也可減少檢視器的延遲。

產生 HTTP 回應的一些常見案例包括下列項目：
+ 傳回小型網頁給檢視器
+ 傳回 HTTP 301 或 302 狀態碼來重新導向使用者到另一個網頁
+ 當使用者尚未驗證時，傳回 HTTP 401 狀態碼至檢視器

當下列 CloudFront 事件發生時，Lambda@Edge 函數可以產生 HTTP 回應事件：

**檢視器請求事件**  
當函數被檢視器請求事件觸發時，CloudFront 會將回應傳回檢視器，而且加以不快取。

**原始伺服器請求事件**  
當函數被原始伺服器請求事件觸發時，CloudFront 會檢查先前函數產生的邊緣快取回應。  
+ 如果回應在快取中，系統不會執行該函數，且 CloudFront 會將快取的回應傳回給檢視器。
+ 如果回應不在快取中，會執行該函數，CloudFront 會將回應傳回給檢視器並加以快取。

若要查看產生 HTTP 回應的範本程式碼，請參閱 [Lambda@Edge 範例函數](lambda-examples.md)。您也可以在回應觸發中取代 HTTP 回應。如需詳細資訊，請參閱[在原始伺服器回應觸發條件中更新 HTTP 回應](#lambda-updating-http-responses)。

### 程式設計模型
<a name="lambda-generating-http-responses-programming-model"></a>

本節說明使用 Lambda@Edge 產生 HTTP 回應的程式設計模型。

**Topics**
+ [回應物件](#lambda-generating-http-responses-object)
+ [錯誤](#lambda-generating-http-responses-errors)
+ [必要欄位](#lambda-generating-http-responses-required-fields)

#### 回應物件
<a name="lambda-generating-http-responses-object"></a>

以 `result` 方法的 `callback` 參數傳回的回應，需具備下列結構 (請注意，僅 `status` 欄位為必要)。

```
const response = {
    body: 'content',
    bodyEncoding: 'text' | 'base64',
    headers: {
        'header name in lowercase': [{
            key: 'header name in standard case',
            value: 'header value'
         }],
         ...
    },
    status: 'HTTP status code (string)',
    statusDescription: 'status description'
};
```

回應物件可以包含以下值：

**`body`**  
如有您希望 CloudFront 在產生的回應中傳回的本文。

**`bodyEncoding`**  
您在 `body` 中指定的值的編碼。唯一的有效編碼是 `text` 和 `base64`。如果您在 `response` 物件中加入 `body`，但省略了 `bodyEncoding`，則 CloudFront 會將內文視為文字。  
如果您將 `bodyEncoding` 指定為 `base64` 但本文不是有效的 base64，CloudFront 會傳回錯誤。

**`headers`**  
您希望 CloudFront 於產生的回應中傳回標頭。注意下列事項：  
+ 在 `headers` 物件的金鑰為標準 HTTP 標頭名稱的小寫版本。使用小寫金鑰提供您區分大小寫的標頭值存取權。
+ 每個標頭 (例如 `headers["accept"]` 或 `headers["host"]`) 是一系列的鍵值組。於已知的標頭，陣列在產生的回應中包含每個值的一組鍵值組。
+ `key` (選用) 為在 HTTP 請求中出現的標頭區分大小寫的名稱，例如 `accept` 或 `host`。
+ 指定 `value` 為標頭值。
+ 如果您未加入索引鍵/值組的標頭索引鍵部分，Lambda@Edge 會自動使用您提供的標頭名稱，來插入標頭索引鍵。無論您如何安排標頭格式，各部分插入的標頭索引鍵名稱都會自動以大寫開頭，以連字號 (-) 分隔。

  例如，您可以不用標頭索引鍵，新增標頭如下：`'content-type': [{ value: 'text/html;charset=UTF-8' }]`

  在這個範例中，Lambda@Edge 建立了下列標頭索引鍵：`Content-Type`。
如需標頭使用限制的詳細資訊，請參閱[對邊緣函數的限制](edge-functions-restrictions.md)。

**`status`**  
HTTP 狀態碼 。以字串形式提供狀態碼。CloudFront 使用提供的狀態碼進行以下操作：  
+ 在回應中傳回
+ 當原始伺服器請求事件觸發的函數產生回應時，在 CloudFront 邊緣快取中快取。
+ 登入 CloudFront [存取日誌 （標準日誌）](AccessLogs.md)
如果 `status` 值不在 200 與 599 之間，CloudFront 會將錯誤傳回至檢視器。

**`statusDescription`**  
您想要 CloudFront 在回應中傳回的描述能搭配 HTTP 狀態碼。您不需要使用標準的描述，例如 HTTP 200 狀態碼為 `OK`。

#### 錯誤
<a name="lambda-generating-http-responses-errors"></a>

以下是產生的 HTTP 回應的可能錯誤。

**回應包含本文與指定 204 (無內容) 狀態**  
當函數是由檢視器請求觸發，當下列二者為 true，CloudFront 會傳回 HTTP 502 狀態碼 (無效的閘道) 至檢視器：  
+ `status` 的值是 204 (無內容)
+ 回應包含 `body` 的值
這是因為 Lambda@Edge 強加於 RFC 2616 中選用的限制，也就是 `HTTP 204` 回應不需要包含訊息本文。

**已產生回應的大小限制**  
由 Lambda 函數產生的回應大小上限取決於觸發函數的事件：  
+ **檢視器請求事件** – 40 KB
+ **原始伺服器請求事件** – 1 MB
如果回應超過允許的大小，CloudFront 會將 HTTP 502 狀態碼 (無效的閘道) 傳回檢視器。

#### 必要欄位
<a name="lambda-generating-http-responses-required-fields"></a>

`status` 欄位是必要的。

所有其他欄位是選用的。

## 在原始伺服器回應觸發條件中更新 HTTP 回應
<a name="lambda-updating-http-responses"></a>

當 CloudFront 從原始伺服器收到 HTTP 回應時，如果某個原始伺服器回應觸發關聯到快取行為，您可以修改 HTTP 回應以覆寫原始伺服器傳回的回應。

更新 HTTP 回應的一些常用案例包括下列項目：
+ 變更狀態以設定 HTTP 200 狀態碼並建立靜態本文內容，以在原始伺服器傳回錯誤狀態碼 (4xx 和 5xx) 時，傳回給檢視器。如需程式碼範例，請參閱 [範例：使用原始伺服器請求觸發以更新錯誤狀態碼為 200](lambda-examples.md#lambda-examples-custom-error-static-body)。
+ 變更狀態來設定 HTTP 301 或 HTTP 302 狀態碼，以在原始伺服器會傳回錯誤狀態碼 (4xx 和 5xx) 時，將使用者重新導向到另一個網站。如需程式碼範例，請參閱 [範例：使用原始伺服器請求觸發以更新錯誤狀態碼為 302](lambda-examples.md#lambda-examples-custom-error-new-site)。

**注意**  
函數必須傳回介於 `200` (含) 和 `599` (含) 之間的狀態值，否則 CloudFront 會將錯誤傳回至檢視器。

您也可以在檢視器與原始伺服器請求事件中取代 HTTP 回應。如需詳細資訊，請參閱[在請求觸發條件中產生 HTTP 回應](#lambda-generating-http-responses-in-requests)。

當您使用 HTTP 回應時，Lambda@Edge 不會公開原始伺服器傳回至原始伺服器回應觸發條件的本文。您可以藉由設定為所需的值來產生靜態內容本文，或藉由設定空值來移除函數內的本文。如果您不更新函數的本文欄位，原始伺服器回傳的原始主體會傳回給檢視器。

## 選擇包含本文選項來存取請求本文
<a name="lambda-include-body-access"></a>

您可以選擇讓 Lambda@Edge 在可寫入的 HTTP 方法 (POST、PUT 和 DELETE 等) 中公開請求的內文，如此您就能在 Lambda 函數中存取該內文。您可以選擇唯讀存取或指定您將替換內文。

若要啟用此選項，請在您為函數建立 CloudFront 觸發條件時 (針對檢視器請求或原始伺服器請求的事件)，選擇 **Include Body (包含內文)**。如需詳細資訊，請參閱 [為 Lambda@Edge 函數新增觸發條件](lambda-edge-add-triggers.md)；或者，若要進一步了解使用**包含內文**與您的函數，請參閱 [Lambda@Edge 事件結構說明頁面](lambda-event-structure.md)。

您可能會想使用此功能的情境，包括下列的案例：
+ 處理 Web 表單，例如「聯絡我們」表單，而不將客戶輸入的資料傳回給原始伺服器。
+ 收集由檢視器的瀏覽器所傳送的網站信標資料，並且在邊緣處理這些資料。

如需程式碼範例，請參閱 [Lambda@Edge 範例函數](lambda-examples.md)。

**注意**  
如果請求主體的資料大小過大，Lambda@Edge 會將主體截斷。如需大小上限和截斷的詳細資訊，請參閱[使用包含內文選項時的要求內文限制](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body)。