

# 使用请求和响应
<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`。如果您在 `body` 对象中包含 `response` 但省略 `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（无内容**  
当函数由查看器请求触发时，如果满足以下情况，则 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 触发器以用于查看器请求或源请求事件时选择**包含正文**。有关更多信息，请参阅[为 Lambda@Edge 函数添加触发器](lambda-edge-add-triggers.md)；要了解如何在函数中使用**包含正文**，请参阅[Lambda@Edge 事件结构](lambda-event-structure.md)。

您可能希望使用此功能的情况包括：
+ 处理 Web 表单（例如“联系我们”表单），而不将客户输入数据发送回源服务器。
+ 收集查看器浏览器发送的 Web 信标数据并在边缘站点中进行处理。

有关代码示例，请参阅 [Lambda@Edge 函数示例](lambda-examples.md)。

**注意**  
如果请求正文很大，Lambda@Edge 将会截断正文。有关最大大小和截断的详细信息，请参阅[具有 Include Body（包含正文）选项的请求正文的限制](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body)。