CloudFront Functions のイベント構造
CloudFront Functions は、関数を実行するときに event
オブジェクトを関数コードに入力として渡します。関数をテストするときは、event
オブジェクトを作成し、関数に渡します。関数をテストするために event
オブジェクトを作成する場合は、context
オブジェクト内の distributionDomainName
、distributionId
、requestId
フィールドを省略できます。ヘッダーの名前が小文字であることを確認してください (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-request
またはviewer-response
)。 requestId
-
CloudFront リクエスト (およびそれに関連付けられたレスポンス) を一意に識別する文字列。
ビューワーオブジェクト
viewer
オブジェクトには、リクエストを送信したビューワー (クライアント) の IP アドレスを値とする ip
フィールドが含まれています。ビューワーリクエストが HTTP プロキシまたはロードバランサーを通して来た場合、値はプロキシまたはロードバランサーの IP アドレスです。
リクエストオブジェクト
request
オブジェクトには、ビューワーから CloudFront への HTTP リクエスト表記が含まれています。関数に渡される event
オブジェクトで、request
オブジェクトは CloudFront がビューワーから受信した実際のリクエストを表しています。
関数コードが CloudFront に request
オブジェクトを返す場合は、これと同じ構造を使用する必要があります。
request
オブジェクトには、以下のフィールドが含まれています。
method
-
リクエストの HTTP メソッド。関数コードが
request
を返す場合、このフィールドは変更できません。これは、request
オブジェクト内唯一の読み取り専用フィールドです。 uri
-
リクエストされたオブジェクトの相対パス。
注記
関数が
uri
値を変更する場合、以下が適用されます。-
新しい
uri
値は、フォワードスラッシュ (/
) で始まる必要があります。 -
関数で
uri
値を変更すると、ビューワーがリクエストしているオブジェクトが変更されます。 -
関数で
uri
値を変更しても、リクエストのキャッシュ動作やオリジンリクエストの送信先は変わりません。
-
querystring
-
リクエストのクエリ文字列を表すオブジェクト。リクエストにクエリ文字列が含まれていない場合でも、
request
オブジェクトには空のquerystring
オブジェクトが含まれています。querystring
オブジェクトには、リクエストのクエリ文字列パラメータ 1 つにつき 1 つのフィールドが含まれます。 headers
-
リクエストの HTTP ヘッダーを表すオブジェクト。リクエストに
Cookie
ヘッダーが含まれている場合、それらのヘッダーはheaders
オブジェクトの一部ではありません。Cookieはcookies
オブジェクトで個別に表示されます。headers
オブジェクトには、リクエストのヘッダー 1 つにつき 1 つのフィールドが含まれます。ヘッダー名は、イベントオブジェクトでは小文字に変換されます。また、関数コードで追加する場合、ヘッダー名を小文字にする必要があります。CloudFront Functions がイベントオブジェクトを HTTP リクエストに変換し直すと、ヘッダー名の各単語の最初の文字が大文字になります。各単語はハイフン (-
) で区切られます。例えば、関数コードがexample-header-name
という名前のヘッダーを追加した場合、CloudFront がこれを HTTP リクエストでExample-Header-Name
に変換します。 cookies
-
リクエスト (
Cookie
ヘッダー) の Cookie を表すオブジェクト。cookies
オブジェクトには、リクエストの Cookie 1 つにつき 1 つのフィールドが含まれます。
クエリ文字列、ヘッダーおよび Cookie の構造の詳細については、「クエリ文字列、ヘッダー、または Cookie の構造」を参照してください。
event
オブジェクトの例については、「イベントオブジェクトの例」を参照してください。
レスポンスオブジェクト
response
オブジェクトには、CloudFront Front からビューワーへの HTTP レスポンス表記が含まれています。関数に渡される event
オブジェクトでは、response
オブジェクトはビューワーリクエストに対する CloudFront の実際の応答を表します。
関数コードが response
オブジェクトを返す場合は、これと同じ構造を使用する必要があります。
response
オブジェクトには、以下のフィールドが含まれています。
statusCode
-
レスポンスの HTTP ステータスコード。この値は文字列ではなく整数です。
関数は
statusCode
を生成または変更できます。 statusDescription
-
レスポンスの HTTP ステータスの説明。関数コードがレスポンスを生成する場合、このフィールドはオプションです。
headers
-
レスポンスの HTTP ヘッダーを表すオブジェクト。レスポンスに
Set-Cookie
ヘッダーが含まれている場合、それらのヘッダーはheaders
オブジェクトの一部ではありません。Cookieはcookies
オブジェクトで個別に表示されます。headers
オブジェクトには、レスポンス内のヘッダー 1 つにつき 1 つのフィールドが含まれます。ヘッダー名は、イベントオブジェクトでは小文字に変換されます。また、関数コードで追加する場合、ヘッダー名を小文字にする必要があります。CloudFront Functions がイベントオブジェクトを HTTP レスポンスに変換し直すと、ヘッダー名の各単語の最初の文字が大文字になります。各単語はハイフン (-
) で区切られます。例えば、関数コードがexample-header-name
という名前のヘッダーを追加した場合、CloudFront がこれを HTTP レスポンスのExample-Header-Name
に変換します。 cookies
-
レスポンス (
Set-Cookie
ヘッダー) で Cookie を表すオブジェクト。cookies
オブジェクトには、レスポンスの Cookie 1 つにつき 1 つのフィールドが含まれます。 body
-
body
フィールドの追加はオプションで、関数で指定しない限りresponse
オブジェクトには表示されません。関数は、CloudFront キャッシュまたはオリジンによって返された元の本文にアクセスできません。ビューワーレスポンス関数でbody
フィールドを指定しない場合、CloudFront キャッシュまたはオリジンから返された元の本文がビューワーに返されます。CloudFront がビューワーにカスタム本文を返すようにするには、
data
フィールドに本文コンテンツを指定し、encoding
フィールドの本文エンコーディングを指定します。エンコーディングは、プレーンテキスト ("encoding": "text"
) または Base64 でエンコードされたコンテンツ ("encoding": "base64"
) として指定できます。ショートカットとして、本文の内容を
body
フィールド ("body": "<specify the body content here>"
) で直接指定することもできます。これを行うときは、data
およびencoding
フィールドを省略してください。この場合、CloudFront は、本文をプレーンテキストとして扱います。encoding
-
body
コンテンツ (data
フィールド) のエンコーディング。有効なエンコードはtext
とbase64
のみです。encoding
をbase64
と指定したが本文が有効な base64 でない場合、CloudFront はエラーを返します。 data
-
body
コンテンツ。
変更されたステータスコードと本文の内容の詳細については、ステータスコードと本文 を参照してください。
ヘッダーと Cookie の構造の詳細については、「クエリ文字列、ヘッダー、または Cookie の構造」を参照してください。
response
オブジェクトの例については、「レスポンスオブジェクトの例」を参照してください。
ステータスコードと本文
CloudFront Functions を使用して、ビューワーのレスポンスステータスコードを更新したり、レスポンス本文すべてを新しく置き換えたり、レスポンス本文を削除したりできます。CloudFront キャッシュまたはオリジンからのレスポンスを評価した後でビューワーのレスポンスを更新する一般的なシナリオには、次のようなものがあります。
-
ステータスを変更して HTTP 200 ステータスコードを設定し、ビューワーに返す静的な本文コンテンツを作成する。
-
HTTP 301 または 302 ステータスコードを設定して、ユーザーを別のウェブサイトにリダイレクトする。
-
ビューワーレスポンスの本文を配信するか削除するかを決定します。
注記
オリジンが 400 以上の HTTP エラーを返した場合、CloudFront Functions は実行されません。詳細については、「すべてのエッジ機能に対する制限」を参照してください。
HTTP レスポンスを使用する場合、CloudFront Functions は、レスポンス本文にアクセスできません。必要な値に設定することで本文コンテンツを置き換えたり、値を空に設定することで本文を削除したりできます。関数内の本文フィールドを更新しない場合は、CloudFront キャッシュまたはオリジンによって返された元の本文がビューワーに返されます。
ヒント
CloudFront Functions を使用して本文を置き換える場合は、content-encoding
、content-type
、content-length
などの対応するヘッダーを新しい本文のコンテンツに合わせてください。
たとえば、CloudFront オリジンまたはキャッシュが content-encoding:
gzip
を返したが、ビューワーレスポンス関数が本文をプレーンテキストに設定した場合、関数は content-encoding
と content-type
ヘッダーもそれに応じて変更する必要があります。
CloudFront Functions が 400 以上の HTTP エラーを返すように設定されている場合、ビューワーには同じステータスコードに対して指定したカスタムエラーページは表示されません。
クエリ文字列、ヘッダー、または Cookie の構造
クエリ文字列、ヘッダー、Cookie は同じ構造を共有します。クエリ文字列は、リクエストに表示される場合があります。ヘッダーは、リクエストとレスポンスに表示されます。Cookie は、リクエストとレスポンスに表示されます。
クエリ文字列、ヘッダーおよび Cookie はすべて、親 querystring
、headers
、cookies
オブジェクトで一意のフィールドです。フィールド名は、クエリ文字列、ヘッダー、または 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
という名前のヘッダーを追加した場合、CloudFront がこれを HTTP リクエストまたはレスポンスの Example-Header-Name
に変換します。
例
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 は request
または response
オブジェクトの 1 つのフィールドに折りたたまれていますが、このフィールドには 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" } ] } }
注記
最初のヘッダー値 (この場合は application/json
) は、value
プロパティと multiValue
プロパティの両方で繰り返されています。これにより、multiValue
配列をループしてすべての値にアクセスできます。
関数コードで変更するクエリ文字列、ヘッダー、または Cookie に multiValue
配列が含まれている場合、CloudFront Functions は以下のルールを使用して変更を適用します。
-
multiValue
配列が存在し、変更がある場合は、その変更が適用されます。value
プロパティの最初の要素は無視されます。 -
それ以外の場合は、
value
プロパティへの変更が適用され、それ以降の値 (存在する場合) は変更されません。
この multiValue
プロパティは、前の例に示すように、HTTP リクエストまたはレスポンスに同じ名前の重複するクエリ文字列、ヘッダー、Cookie のいずれかが含まれている場合にのみ使用されます。ただし、1 つのクエリ文字列、ヘッダー、または Cookie に複数の値がある場合、multiValue
プロパティは使用されません。
例
3 つの値を含む 1 つの Accept
ヘッダーを持つリクエストについて考えてみます。
Accept: application/json, application/xml, text/html
このヘッダーは、request
オブジェクトで次のように表されます。
"headers": { "accept": { "value": "application/json, application/xml, text/html" } }
Cookie 属性
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
オブジェクトは関数への入力です。関数は、event
オブジェクト全体ではなく、request
または response
オブジェクトだけを返します。
{ "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" } ] } } } }