Lambda@Edge 事件结构
下面的主题介绍了触发 Lambda@Edge 函数时,CloudFront 传递给该函数的请求和响应事件对象。
动态源选择
您可以在缓存行为中使用路径模式,根据所请求对象的路径和名称将请求路由到源,例如 images/*.jpg
。使用 Lambda@Edge,您也可以基于其他功能将请求路由到源,例如请求标头中的值。
在多种情况下,这种动态源选择会非常有用。例如,您可以跨不同地理区域中的源分配请求,帮助实现全球负载均衡。或者,您可以选择性地将请求路由到不同的源,每个服务器提供特定功能:自动程序处理、SEO 优化、身份验证等。有关演示如何使用此功能的代码示例,请参阅 基于内容的动态源选择 - 示例。
在 CloudFront 源请求事件中,根据路径模式,事件结构中的 origin
对象包含有关将请求路由到的源的信息。您可以更新 origin
对象中的值,将请求路由到不同的源。更新 origin
对象时,您不需要在分配中定义源。您还可以将 Amazon S3 源对象替换为自定义源对象,或者执行相反的操作。但是,只能为每个请求指定一个源;该源可以是自定义源,也可以是 Amazon S3 源,但不能同时指定这两种源。
请求事件
下面的主题显示了 CloudFront 传递给查看器和源请求事件的 Lambda 函数的对象结构。这些示例显示了不带正文的 GET
请求。下面一些示例中,列出了查看器和源请求事件中的所有的可能字段。
示例查看器请求
下面的示例显示查看器请求事件对象。
{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "viewer-request", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "host": [ { "key": "Host", "value": "d111111abcdef8.cloudfront.net" } ], "user-agent": [ { "key": "User-Agent", "value": "curl/7.66.0" } ], "accept": [ { "key": "accept", "value": "*/*" } ] }, "method": "GET", "querystring": "", "uri": "/" } } } ] }
示例源请求
下面的示例显示源请求事件对象。
{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "origin-request", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "x-forwarded-for": [ { "key": "X-Forwarded-For", "value": "203.0.113.178" } ], "user-agent": [ { "key": "User-Agent", "value": "Amazon CloudFront" } ], "via": [ { "key": "Via", "value": "2.0 2afae0d44e2540f472c0635ab62c232b.cloudfront.net (CloudFront)" } ], "host": [ { "key": "Host", "value": "example.org" } ], "cache-control": [ { "key": "Cache-Control", "value": "no-cache" } ] }, "method": "GET", "origin": { "custom": { "customHeaders": {}, "domainName": "example.org", "keepaliveTimeout": 5, "path": "", "port": 443, "protocol": "https", "readTimeout": 30, "sslProtocols": [ "TLSv1", "TLSv1.1", "TLSv1.2" ] } }, "querystring": "", "uri": "/" } } } ] }
请求事件字段
请求事件对象数据包含在两个子对象中:config
(Records.cf.config
) 和 request
(Records.cf.request
)。下面的列表描述了各个子对象的字段。
Config 对象中的字段
下面的列表介绍了 config
对象 (Records.cf.config
) 中的字段。
distributionDomainName
(只读)-
与请求关联的分配的域名。
distributionID
(只读)-
与请求关联的分配的 ID。
eventType
(只读)-
与请求关联的触发器类型:
viewer-request
或origin-request
。 requestId
(只读)-
一个加密字符串,唯一地标识查看器到 CloudFront 的请求。
requestId
值还在 CloudFront 访问日志中显示为x-edge-request-id
。有关更多信息,请参阅 配置和使用标准日志(访问日志)和 标准日志文件字段:
请求对象中的字段
下面的列表介绍了 request
对象 (Records.cf.request
) 中的字段。
clientIp
(只读)-
发出请求的查看器的 IP 地址。如果查看器使用 HTTP 代理或负载均衡器发送请求,则值为该代理或负载均衡器的 IP 地址。
- 标头(读/写)
-
请求中的标头。请注意以下几点:
-
headers
对象中的键为标准 HTTP 请求标头名称的小写版本。使用小写键可为您提供对标头值的不区分大小写的访问权限。 -
每个标头对象(例如,
headers["accept"]
或headers["host"]
)是一个键/值对数组。对于一个指定标头,数组为请求中的每个值包含一个键/值对。 -
key
包含 HTTP 请求中显示的标头的名称,名称区分大小写;例如Host
、User-Agent
、X-Forwarded-For
等等。 -
value
包含 HTTP 请求中显示的标头值。 -
当您的 Lambda 函数添加或修改请求标头,并且您未包含标头
key
字段时,Lambda@Edge 会自动使用您提供的标头名称插入标头key
。无论您如何格式化标头名称,自动插入的标头键都将通过对每个部分使用首字母大写方式 [用连字符 (-) 分隔] 来格式化。例如,您可以不带标头键添加标头
key
,如下所示:"user-agent": [ { "value": "ExampleCustomUserAgent/1.X.0" } ]
在本示例中,Lambda@Edge 会自动插入
"key": "User-Agent"
。
有关标头使用情况限制的信息,请参阅边缘函数的限制。
-
method
(只读)-
请求中的 HTTP 方法。
querystring
(读/写)-
请求中的查询字符串(如果有的话)。如果请求中不包括查询字符串,则事件对象仍包括带空值的
querystring
。有关查询字符串的更多信息,请参阅根据查询字符串参数缓存内容。 uri
(读/写)-
所请求对象的相对路径。如果您的 Lambda 函数修改了
uri
值,请记住以下事项:-
新的
uri
值必须以正斜杠 (/) 开头。 -
如果某个函数更改
uri
值,则这样会更改查看器请求的对象。 -
如果某个函数更改
uri
值,则这样不会 更改该请求或该请求发送到的源的缓存行为。
-
body
(读/写)-
HTTP 请求的正文。
body
结构可以包含以下字段:inputTruncated
(只读)-
一个布尔值标记,它指示 Lambda@Edge 是否截断正文。有关更多信息,请参阅 具有 Include Body(包含正文)选项的请求正文的限制。
action
(读/写)-
您打算对正文执行的操作。
action
选项如下所示:-
read-only:
这是默认值。在从 Lambda 函数返回响应时,如果action
是只读的,Lambda@Edge 将忽略对encoding
或data
的任何更改。 -
replace:
如果要替换发送到源的正文,请指定该选项。
-
encoding
(读/写)-
正文的编码。在 Lambda@Edge 向 Lambda 函数公开正文时,它先将正文转换为 base64-encoding。如果您为
action
选择replace
以替换正文,您可以选择使用base64
(默认编码)或text
编码。如果将encoding
指定为base64
,但正文不是有效的 base64,CloudFront 将返回错误。 data
(读/写)-
请求正文内容。
origin
(读/写)(仅限原始事件)-
要将请求发送到的源。
origin
结构只能包含一个源,它可以是自定义源或 Amazon S3 源。源结构可以包含以下字段:customHeaders
(读/写)(自定义和 Amazon S3 源)-
您可以通过为每个自定义标头指定标头名称/值对,在请求中包括自定义标头。您不能添加不允许使用的标头,并且
Records.cf.request.headers
中不能存在同名标头。有关请求标头的注释也适用于自定义标头。有关更多信息,请参阅 CloudFront 无法添加到源请求的自定义标头和 边缘函数的限制: domainName
(读/写)(自定义和 Amazon S3 源)-
源的域名。域名不能为空。
-
对于自定义源 – 指定 DNS 域名,例如
www.example.com
。域名不能包含冒号 (:),也不能为 IP 地址。域名最多可以有 253 个字符。 -
对于 Amazon S3 源 – 指定 Amazon S3 存储桶的 DNS 域名,例如
amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com
。名称必须最多为 128 个字符,并且必须为全小写。
-
path
(读/写)(自定义和 Amazon S3 源)-
源上的目录路径,请求应在其中查找内容。路径应该以正斜杠 (/) 开头,但不应该以正斜杠结尾(例如,它不应该以
example-path/
结尾)。仅对于自定义源,路径应为 URL 编码,最大长度为 255 个字符。 keepaliveTimeout
(读/写)(仅自定义源)-
CloudFront 在接收最后一个响应数据包后应尝试与源保持连接的秒数。该值必须是 1 到 60 之间(含)的数字。
port
(读/写)(仅自定义源)-
自定义源中 CloudFront 应连接到的端口。端口必须为 80、443,或者是 1024 到 65535 之间(含)的数字。
protocol
(读/写)(仅自定义源)-
连接到您的源时 CloudFront 应使用的连接协议。该值可以是
http
或https
。 readTimeout
(读/写)(仅自定义源)-
向您的源发送请求后 CloudFront 应等待响应多长时间,以秒为单位。这还指定在 CloudFront 接收响应数据包之后应等待多长时间,然后再接收下一个数据包。该值必须是 4 到 60 之间(含)的数字。
如果您的使用案例需要的时间超过 60 秒,则可以为
Response timeout per origin
请求更高的配额。有关更多信息,请参阅 分配的一般配额。 sslProtocols
(读/写)(仅自定义源)-
CloudFront 在建立与您的源的 HTTPS 连接时可使用的最小 SSL/TLS 协议。可以是以下值之一:
TLSv1.2
、TLSv1.1
、TLSv1
或SSLv3
。 authMethod
(读/写)(仅限 Amazon S3 源)-
如果您使用源访问身份 (OAI),请将此字段设置为
origin-access-identity
。如果您没有使用 OAI,请将其设置为none
。将authMethod
设置为origin-access-identity
时有以下几点要求:-
您必须指定
region
(请参阅以下字段)。 -
将请求从一个 Amazon S3 源更改为另一个源时,必须使用相同的 OAI。
-
将请求从自定义源更改为 Amazon S3 源时,不能使用 OAI。
注意
此字段不支持源访问控制(OAC)。
-
region
(读/写)(仅限 Amazon S3 源)-
您的 Amazon S3 存储桶的 AWS 区域。仅当您将
authMethod
设置为origin-access-identity
时,此项才是必需的。
响应事件
下面的主题显示了 CloudFront 传递给查看器和源响应事件的 Lambda 函数的对象结构。下面的示例是查看器和源响应事件中所有可能字段的列表。
示例源响应
下面的示例显示源响应事件对象。
{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "origin-response", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "x-forwarded-for": [ { "key": "X-Forwarded-For", "value": "203.0.113.178" } ], "user-agent": [ { "key": "User-Agent", "value": "Amazon CloudFront" } ], "via": [ { "key": "Via", "value": "2.0 8f22423015641505b8c857a37450d6c0.cloudfront.net (CloudFront)" } ], "host": [ { "key": "Host", "value": "example.org" } ], "cache-control": [ { "key": "Cache-Control", "value": "no-cache" } ] }, "method": "GET", "origin": { "custom": { "customHeaders": {}, "domainName": "example.org", "keepaliveTimeout": 5, "path": "", "port": 443, "protocol": "https", "readTimeout": 30, "sslProtocols": [ "TLSv1", "TLSv1.1", "TLSv1.2" ] } }, "querystring": "", "uri": "/" }, "response": { "headers": { "access-control-allow-credentials": [ { "key": "Access-Control-Allow-Credentials", "value": "true" } ], "access-control-allow-origin": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ], "date": [ { "key": "Date", "value": "Mon, 13 Jan 2020 20:12:38 GMT" } ], "referrer-policy": [ { "key": "Referrer-Policy", "value": "no-referrer-when-downgrade" } ], "server": [ { "key": "Server", "value": "ExampleCustomOriginServer" } ], "x-content-type-options": [ { "key": "X-Content-Type-Options", "value": "nosniff" } ], "x-frame-options": [ { "key": "X-Frame-Options", "value": "DENY" } ], "x-xss-protection": [ { "key": "X-XSS-Protection", "value": "1; mode=block" } ], "content-type": [ { "key": "Content-Type", "value": "text/html; charset=utf-8" } ], "content-length": [ { "key": "Content-Length", "value": "9593" } ] }, "status": "200", "statusDescription": "OK" } } } ] }
示例查看器响应
下面的示例显示查看器响应事件对象。
{ "Records": [ { "cf": { "config": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "viewer-response", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "host": [ { "key": "Host", "value": "d111111abcdef8.cloudfront.net" } ], "user-agent": [ { "key": "User-Agent", "value": "curl/7.66.0" } ], "accept": [ { "key": "accept", "value": "*/*" } ] }, "method": "GET", "querystring": "", "uri": "/" }, "response": { "headers": { "access-control-allow-credentials": [ { "key": "Access-Control-Allow-Credentials", "value": "true" } ], "access-control-allow-origin": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ], "date": [ { "key": "Date", "value": "Mon, 13 Jan 2020 20:14:56 GMT" } ], "referrer-policy": [ { "key": "Referrer-Policy", "value": "no-referrer-when-downgrade" } ], "server": [ { "key": "Server", "value": "ExampleCustomOriginServer" } ], "x-content-type-options": [ { "key": "X-Content-Type-Options", "value": "nosniff" } ], "x-frame-options": [ { "key": "X-Frame-Options", "value": "DENY" } ], "x-xss-protection": [ { "key": "X-XSS-Protection", "value": "1; mode=block" } ], "age": [ { "key": "Age", "value": "2402" } ], "content-type": [ { "key": "Content-Type", "value": "text/html; charset=utf-8" } ], "content-length": [ { "key": "Content-Length", "value": "9593" } ] }, "status": "200", "statusDescription": "OK" } } } ] }
响应事件字段
响应事件对象数据包含在三个子对象中:config
(Records.cf.config
)、request
(Records.cf.request
) 和 response
(Records.cf.response
)。有关请求对象中的字段的更多信息,请参阅请求对象中的字段。下面的列表描述了 config
和 response
子对象中的字段。
Config 对象中的字段
下面的列表介绍了 config
对象 (Records.cf.config
) 中的字段。
distributionDomainName
(只读)-
与响应关联的分配的域名。
distributionID
(只读)-
与响应关联的分配的 ID。
eventType
(只读)-
与响应关联的触发器的类型:
origin-response
或viewer-response
。 requestId
(只读)-
一个加密字符串,唯一地标识与此响应关联的查看器到 CloudFront 的请求。
requestId
值还在 CloudFront 访问日志中显示为x-edge-request-id
。有关更多信息,请参阅 配置和使用标准日志(访问日志)和 标准日志文件字段:
响应对象中的字段
下面的列表介绍了 response
对象 (Records.cf.response
) 中的字段。有关使用 Lambda@Edge 函数生成 HTTP 响应的信息,请参阅在请求触发器中生成 HTTP 响应。
headers
(读/写)-
响应中的标头。请注意以下几点:
-
headers
对象中的键为标准 HTTP 请求标头名称的小写版本。使用小写键可为您提供对标头值的不区分大小写的访问权限。 -
每个标头对象(例如,
headers["content-type"]
或headers["content-length"]
)是一个键/值对数组。对于一个指定标头,数组为响应中的每个值包含一个键/值对。 -
key
包含 HTTP 响应中显示的标头的名称,名称区分大小写;例如Content-Type
、Content-Length
、Cookie
等等。 -
value
包含 HTTP 响应中显示的标头值。 -
当您的 Lambda 函数添加或修改响应标头,并且您不包含标头
key
字段时,Lambda@Edge 会自动使用您提供的标头名称插入标头key
。无论您如何格式化标头名称,自动插入的标头键都将通过对每个部分使用首字母大写方式 [用连字符 (-) 分隔] 来格式化。例如,您可以不带标头键添加标头
key
,如下所示:"content-type": [ { "value": "text/html;charset=UTF-8" } ]
在本示例中,Lambda@Edge 会自动插入
"key": "Content-Type"
。
有关标头使用情况限制的信息,请参阅边缘函数的限制。
-
status
-
响应的 HTTP 状态代码。
statusDescription
-
响应的 HTTP 状态描述。