CloudFront 函數事件結構 - Amazon CloudFront

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

CloudFront 函數事件結構

CloudFront 函數會在執行函數時,將event物件傳遞至函數程式碼做為輸入。測試函數時,建立 event 物件並將其傳遞給函數。建立用於測試函數的 event 物件時,您可以省略 distributionDomainName 物件中的 distributionIdrequestIdcontext 欄位。確保標題的名稱是小寫的,在 CloudFront Functions 在生產中傳遞給函數的event對象中始終如此。

以下是此事件物件結構的概觀。

{ "version": "1.0", "context": { <context object> }, "viewer": { <viewer object> }, "request": { <request object> }, "response": { <response object> } }

如需詳細資訊,請參閱下列主題:

版本欄位

version欄位包含字串,指定 CloudFront Functions 事件物件的版本。目前版本是 1.0

內容物件

context 物件包含有關事件的關聯式資訊。它包括以下欄位:

distributionDomainName

與事件相關聯的發行版的網 CloudFront 域名稱 (例如,d111111abcdef8.cloudfront.net)。

distributionId

與事件相關聯的發佈的 ID (例如 EDFDVBD6EXAMPLE)。

eventType

事件類型,viewer-requestviewer-response

requestId

唯一識別 CloudFront 要求 (及其相關回應) 的字串。

檢視者物件

viewer 物件包含一個 ip 欄位,其值是傳送請求的檢視者 (用戶端) 的 IP 地址。如果檢視者的請求來自 HTTP 代理或負載平衡器,此值為代理或負載平衡器的 IP 地址。

請求物件

request對象包含查看器對 HTTP 請求的表示。CloudFront 在傳遞給函數的event對象中,該request對象表示從查看器 CloudFront 收到的實際請求。

如果您的函數代碼返回一個request對象 CloudFront,它必須使用相同的結構。

request 物件包含下列欄位:

method

請求的 HTTP 方法。如果您的函數代碼返回 arequest,則無法修改此字段。這是 request 物件中唯一的唯讀欄位。

uri

請求物件的相對路徑。

注意

如果您的函數修改了uri值,則適用以下內容:

  • 全新的 uri 值必須以正斜線 (/) 作為開頭。

  • 當函數變更 uri 值時,它會變更檢視者請求的物件。

  • 當函數變更 uri 值時,它不會變更請求的快取行為或原始伺服器請求傳送的來源。

querystring

代表請求中的查詢字串的物件。如果請求不包含查詢字串,request 物件仍會包含空白的 querystring 物件。

querystring 物件針對請求中的每個查詢字串參數包含一個欄位。

headers

代表請求中 HTTP 標頭的物件。如果請求包含任何 Cookie 標頭,則這些標頭不是 headers 物件的一部分。Cookies 在 cookies 物件中單獨表示。

headers 物件針對請求中的每個標頭包含一個欄位。在事件物件中,標頭名稱會轉換為小寫,而在函數程式碼新增標頭名稱時,標頭名稱必須是小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 要求時,標頭名稱中每個單字的第一個字母都會大寫。單字以連字號分隔 (-)。例如,如果您的函數代碼添加了一個名為的標頭example-header-name,請在 HTTP 請求Example-Header-Name中將其 CloudFront 轉換為。

cookies

代表請求 (Cookie 標頭) 中 Cookie 的物件。

cookies 物件針對請求中的每個 Cookie 包含一個欄位。

如需有關查詢字串、標頭和 Cookie 結構的詳細資訊,請參閱 查詢字串、標頭和 Cookie 的結構

如需範例 event 物件,請參閱 範例事件物件

回應物件

該對response象包含 CloudFront對查看者 HTTP 響應的表示。在傳遞給函數的event對象中,該response對象代表 CloudFront對查看器請求的實際響應。

如果您的函數程式碼返回 response 物件,其必須使用相同的結構。

response 物件包含下列欄位:

statusCode

回應的 HTTP 狀態碼。該值是一個整數,而不是字串。

您的函數可以產生或修改 statusCode

statusDescription

回應的 HTTP 狀態說明。如果您的函數程式碼產生回應,則此欄位為選用。

headers

代表回應中 HTTP 標頭的物件。如果回應包含任何 Set-Cookie 標頭,則這些標頭不是 headers 物件的一部分。Cookies 在 cookies 物件中單獨表示。

headers 物件針對回應中的每個標頭包含一個欄位。在事件物件中,標頭名稱會轉換為小寫,而在函數程式碼新增標頭名稱時,標頭名稱必須是小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 回應時,標頭名稱中每個單字的第一個字母都會大寫。單字以連字號分隔 (-)。例如,如果您的函數代碼添加了一個名為的標頭example-header-name,請在 HTTP 響應Example-Header-Name中將其 CloudFront 轉換為。

cookies

代表回應 (Set-Cookie 標頭) 中 Cookie 的物件。

cookies 物件針對回應中的每個 Cookie 包含一個欄位。

body

新增 body 欄位是選擇性的,除非您在函數中進行指定,否則它不會出現在 response 物件中。您的函數無法訪問 CloudFront緩存或 origin 返回的原始主體。如果您沒有在檢視器回應函式中指定body欄位, CloudFront 快取或 origin 傳回的原始主體會傳回給檢視者。

如果您想 CloudFront 要將自訂內文傳回給檢視器,請在欄位中指定內文內容,並在data欄位中指定encoding內文編碼。您可以將編碼指定為純文字 ("encoding": "text") 或 Base64 編碼的內容 ("encoding": "base64")。

作為捷徑,您也可以直接在 body 欄位 ("body": "<specify the body content here>") 中指定本文內容。執行此操作時,請省略dataencoding欄位。 CloudFront 在這種情況下,將正文視為純文本。

encoding

body 內容 (data 欄位) 的編碼。唯一的有效編碼是 textbase64

如果您指定encoding為,base64但主體不是有效的 base64,則 CloudFront 返回一個錯誤。

data

body 內容。

如需有關已修改狀態碼和本文內容的更多資訊,請參閱 狀態碼和本文

如需有關標頭和 Cookie 結構的詳細資訊,請參閱 查詢字串、標頭和 Cookie 的結構

如需範例 response 物件,請參閱 範例回應物件

狀態碼和本文

透過 CloudFront Functions,您可以更新檢視器回應狀態碼、以新的回應內文取代整個回應本文,或移除回應內文。在評估 CloudFront快取或來源回應的各個層面之後,更新檢視器回應的一些常見案例包括:

  • 變更狀態以設定 HTTP 200 狀態碼並建立靜態本文內容,以傳回給檢視器。

  • 變更狀態以設定 HTTP 301 或 302 狀態碼來重新導向使用者到另一個網站。

  • 決定是否要提供或捨棄檢視者回應的本文。

注意

如果來源傳回 400 及以上的 HTTP 錯誤, CloudFront 函式將無法執行。如需更多資訊,請參閱對所有邊緣函數的限制

當您使用 HTTP 響應時, CloudFront 函數無法訪問響應主體。您可以透過將本文內容設定為所需的值來進行替換,或設定為空值來移除本文。如果您不更新函數中的 body 字段,則 CloudFront 緩存或 origin 返回的原始主體將返回給查看者。

提示

使用 CloudFront Functions 來取代主體時,請務必將對應的標題 (例如content-encodingcontent-typecontent-length、或) 對齊新的本文內容。

例如,如果 CloudFront 原點或緩存返回,content-encoding: gzip但查看器響應函數設置了純文本的主體,該函數也需要相應地更改content-encodingcontent-type標題。

如果您的 CloudFront 函數配置為返回 400 或更高的 HTTP 錯誤,您的查看器將不會看到您為相同狀態碼指定的自定義錯誤頁面

查詢字串、標頭和 Cookie 共用相同的結構。查詢字串可能會出現在請求中。標頭會出現在請求和回應中。Cookie 會出現在請求和回應中。

每個查詢字串、標頭或 Cookie 都是父系 querystringheaderscookies 物件中的唯一欄位。欄位名稱是查詢字串、標頭或 Cookie 的名稱。每個欄位都包含具有查詢字串、標頭或 Cookie 值的 value 屬性。

查詢字串值或查詢字串物件

除了查詢字串物件之外,函數還可以傳回查詢字串值。查詢字串值可用來依任意自訂順序排列查詢字串參數。

範例

若要修改函數程式碼中的查詢字串,請使用如下所示的程式碼。

var request = event.request; request.querystring = 'ID=42&Exp=1619740800&TTL=1440&NoValue=&querymv=val1&querymv=val2,val3';

標頭的特殊考量

僅針對標頭,標頭名稱會在事件物件中轉換為小寫,而在函數程式碼新增標頭名稱時,標頭名稱則必須是小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 要求或回應時,標頭名稱中每個單字的第一個字母都會大寫。單字以連字號分隔 (-)。例如,如果您的函數代碼添加了一個名為的標頭example-header-name,請Example-Header-Name在 HTTP 請求或響應中將其 CloudFront 轉換為。

範例

請在 HTTP 要求中考慮下列Host標頭。

Host: video.example.com

此標頭在 request 物件中的表示方式如下:

"headers": { "host": { "value": "video.example.com" } }

若要在函數程式碼中存取 Host 標頭,請使用如下所示的程式碼:

var request = event.request; var host = request.headers.host.value;

若要在函數程式碼中新增或修改標頭,請使用如下所示的程式碼 (此程式碼會新增名為 X-Custom-Header 且包含值 example value 的標頭):

var request = event.request; request.headers['x-custom-header'] = {value: 'example value'};

重複的查詢字串、標頭和 Cookie (multiValue 陣列)

HTTP 請求或回應可以包含多個具有相同名稱的查詢字串、標頭或 Cookie。在此情況下,重複的查詢字串、標頭或 Cookie 會折疊成 requestresponse 物件中的一個欄位,但此欄位包含一個名為 multiValue 的額外屬性。multiValue 屬性包含一個陣列,其中帶有每個重複查詢字串、標頭或 Cookie 的值。

範例

考慮一個帶有以下Accept標頭的 HTTP 請求。

Accept: application/json Accept: application/xml Accept: text/html

這些標頭在request對象中表示如下。

"headers": { "accept": { "value": "application/json", "multiValue": [ { "value": "application/json" }, { "value": "application/xml" }, { "value": "text/html" } ] } }
注意

valuemultiValue屬性中會重複第一個標頭值 (在本例中為application/json)。這可讓您透過在 multiValue 陣列中執行迴圈來存取所有值。

如果您的函數程式碼修改了具有multiValue陣列的查詢字串、標頭或 Cookie, CloudFront Functions 會使用下列規則來套用變更:

  1. 如果 multiValue 陣列存在且有任何修改,則套用此修改。value 屬性中的第一個元素被忽略。

  2. 否則,會套用 value 屬性的任何修改,並且後續的值 (如果存在) 保持不變。

只有當 HTTP 請求或回應包含具有相同名稱的重複查詢字串、標頭或 Cookie 時,才會使用 multiValue 屬性,如上述範例所示。但是,如果單一查詢字串、標頭或 Cookie 中有多個值,則不會使用該 multiValue 屬性。

範例

考慮一個包含三個值的Accept標頭的請求。

Accept: application/json, application/xml, text/html

此標頭在request對象中表示如下。

"headers": { "accept": { "value": "application/json, application/xml, text/html" } }

在 HTTP 回應的 Set-Cookie 標頭中,標頭包含 Cookie 的名稱/值對,以及選用的一組屬性 (以分號分隔)。

範例
Set-Cookie: cookie1=val1; Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT

response 物件中,這些屬性會在 Cookie 欄位的 attributes 屬性中表示。例如,前面的 Set-Cookie 標頭表示如下:

"cookie1": { "value": "val1", "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT" }

範例回應物件

以下範例顯示一個本文已被檢視器回應函數替換的 response 物件 (檢視器回應函數的輸出)。

{ "response": { "statusCode": 200, "statusDescription": "OK", "headers": { "date": { "value": "Mon, 04 Apr 2021 18:57:56 GMT" }, "server": { "value": "gunicorn/19.9.0" }, "access-control-allow-origin": { "value": "*" }, "access-control-allow-credentials": { "value": "true" }, "content-type": { "value": "text/html" }, "content-length": { "value": "86" } }, "cookies": { "ID": { "value": "id1234", "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT" }, "Cookie1": { "value": "val1", "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT", "multiValue": [ { "value": "val1", "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT" }, { "value": "val2", "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT" } ] } }, // Adding the body field is optional and it will not be present in the response object // unless you specify it in your function. // Your function does not have access to the original body returned by the CloudFront // cache or origin. // If you don't specify the body field in your viewer response function, the original // body returned by the CloudFront cache or origin is returned to viewer. "body": { "encoding": "text", "data": "<!DOCTYPE html><html><body><p>Here is your custom content.</p></body></html>" } } }

範例事件物件

以下範例顯示完整的 event 物件。

注意

event 物件是函數的輸入。您的函數僅返回 requestresponse 物件,而不是完整的 event 物件。

{ "version": "1.0", "context": { "distributionDomainName": "d111111abcdef8.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "viewer-response", "requestId": "EXAMPLEntjQpEXAMPLE_SG5Z-EXAMPLEPmPfEXAMPLEu3EqEXAMPLE==" }, "viewer": {"ip": "198.51.100.11"}, "request": { "method": "GET", "uri": "/media/index.mpd", "querystring": { "ID": {"value": "42"}, "Exp": {"value": "1619740800"}, "TTL": {"value": "1440"}, "NoValue": {"value": ""}, "querymv": { "value": "val1", "multiValue": [ {"value": "val1"}, {"value": "val2,val3"} ] } }, "headers": { "host": {"value": "video.example.com"}, "user-agent": {"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"}, "accept": { "value": "application/json", "multiValue": [ {"value": "application/json"}, {"value": "application/xml"}, {"value": "text/html"} ] }, "accept-language": {"value": "en-GB,en;q=0.5"}, "accept-encoding": {"value": "gzip, deflate, br"}, "origin": {"value": "https://website.example.com"}, "referer": {"value": "https://website.example.com/videos/12345678?action=play"}, "cloudfront-viewer-country": {"value": "GB"} }, "cookies": { "Cookie1": {"value": "value1"}, "Cookie2": {"value": "value2"}, "cookie_consent": {"value": "true"}, "cookiemv": { "value": "value3", "multiValue": [ {"value": "value3"}, {"value": "value4"} ] } } }, "response": { "statusCode": 200, "statusDescription": "OK", "headers": { "date": {"value": "Mon, 04 Apr 2021 18:57:56 GMT"}, "server": {"value": "gunicorn/19.9.0"}, "access-control-allow-origin": {"value": "*"}, "access-control-allow-credentials": {"value": "true"}, "content-type": {"value": "application/json"}, "content-length": {"value": "701"} }, "cookies": { "ID": { "value": "id1234", "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT" }, "Cookie1": { "value": "val1", "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT", "multiValue": [ { "value": "val1", "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT" }, { "value": "val2", "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT" } ] } } } }