

# 関数を使用してエッジでカスタマイズする
<a name="edge-functions"></a>

Amazon CloudFront では、独自のコードを記述して、CloudFront ディストリビューションプロセスが HTTP リクエストとレスポンスを処理する方法をカスタマイズできます。このコードは、レイテンシーを最小限に抑えるためにビューワー (ユーザー) の近くで実行するため、サーバーやその他のインフラストラクチャを管理する必要はありません。CloudFront を通過するリクエストとレスポンスの操作、基本認証と認可の実行、エッジでの HTTP レスポンスの生成などのコードを記述できます。

CloudFront ディストリビューションに記述してアタッチするコードは、*エッジ関数*と呼ばれます。CloudFront でエッジ関数の記述と管理をする方法は 2 つあります。

**CloudFront Functions**  
大規模でレイテンシーの影響を受けやすい CDN カスタマイズのための軽量な関数を JavaScript で記述できます。CloudFront Functions の runtime 環境は、起動時間が 1 ミリ秒未満、毎秒数百万のリクエストを処理するようにすぐにスケールでき、高い安全性を誇ります。CloudFront Functions は、CloudFront のネイティブ関数です。つまり、CloudFront 内でコードを完全に構築、テスト、デプロイできます。

**Lambda@Edge**  
Lambda@Edge は、複雑な関数および完全なアプリケーションロジックをビューワーに近い場所で実行するための強力で柔軟なコンピューティングを提供する、安全性に優れた [AWS Lambda](https://aws.amazon.com/lambda/) の拡張機能です。Lambda@Edge 関数は、Node.js または Python runtime 環境で実行されます。これらの関数の発行先は単一の AWS リージョンですが、CloudFront ディストリビューションに関数を関連付けると、Lambda@Edge がコードを世界中に自動的にレプリケートします。

CloudFront で AWS WAF を実行する場合、AWS WAF の挿入されたヘッダーを CloudFront Functions と Lambda@Edge の両方で使用できます。これはビューワーとオリジンのリクエストとレスポンスで機能します。

**Topics**
+ [CloudFront Functions と Lambda@Edge の違い](edge-functions-choosing.md)
+ [CloudFront Functions を使用してエッジでカスタマイズする](cloudfront-functions.md)
+ [CloudFront Connection Functions でカスタマイズする](customize-connections-validation-with-connection-functions.md)
+ [Lambda@Edge を使用してエッジでカスタマイズする](lambda-at-the-edge.md)
+ [エッジ関数に対する制限](edge-functions-restrictions.md)

# CloudFront Functions と Lambda@Edge の違い
<a name="edge-functions-choosing"></a>

CloudFront Functions と Lambda@Edge は、どちらでもCloudFront イベントに応答してコードを実行できます。

CloudFront Functions は、以下のユースケースにおける軽量で実行時間の短い関数に最適です。
+ **キャッシュキーの正規化** – HTTP リクエスト属性 (ヘッダー、クエリ文字列、Cookie、さらには URL パス) を変換して、最適な[キャッシュキー](understanding-the-cache-key.md)を作成します。これにより、キャッシュのヒット率を向上させることができます。
+ **ヘッダー操作** – リクエストまたはレスポンスに対する HTTP ヘッダーの挿入、変更、または削除を行います。たとえば、すべてのリクエストに `True-Client-IP` ヘッダーを追加できます。
+ **URL リダイレクトまたは書き換え** – リクエスト内の情報に基づいてビューワーを他のページにリダイレクトしたり、あるパスから別のパスにすべてのリクエストを書き換えたりします。
+ **リクエストの承認** – 承認ヘッダーや他のリクエストメタデータを調べることで、JSON ウェブトークン (JWT) などのハッシュ化された承認トークンを検証します。

CloudFront Functions の使用を開始するには、「[CloudFront Functions を使用してエッジでカスタマイズする](cloudfront-functions.md)」を参照してください。

Lambda@Edge は、以下のユースケースに最適です。
+ 完了までに数ミリ秒以上かかる関数。
+ 調整可能な CPU またはメモリを必要とする機能。
+ サードパーティライブラリに依存する関数 (他の AWS のサービスとの統合のため、AWS SDK を含む)。
+ 外部サービスを使用して処理するために、ネットワークアクセスを必要とする関数。
+ ファイルシステムへのアクセスまたは HTTP リクエストの本文へのアクセスを必要とする関数。

Lambda@Edge の使用を開始するには、「[Lambda@Edge を使用してエッジでカスタマイズする](lambda-at-the-edge.md)」を参照してください。

次の表を使用して CloudFront Functions と Lambda@Edge の違いを理解すると、ユースケースのオプションを選択しやすくなります。オリジン変更ヘルパーメソッドに適用される違いについての詳細は、「[CloudFront Functions と Lambda@Edge のどちらかを選択する](helper-functions-origin-modification.md#origin-modification-considerations)」を参照してください。


|  | CloudFront Functions | Lambda@Edge | 
| --- | --- | --- | 
| プログラミング言語 | JavaScript (ECMAScript 5.1 準拠) | Node.js と Python | 
| イベントソース |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/edge-functions-choosing.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/edge-functions-choosing.html)  | 
|  [Amazon CloudFront KeyValueStore](kvs-with-functions.md) をサポートする  |  はい CloudFront KeyValueStore は [JavaScript ランタイム 2.0](functions-javascript-runtime-20.md) のみをサポートします  |  いいえ  | 
| スケール | 1 秒あたり最大数百万のリクエスト | リクエスト数: 1 リージョンあたり毎秒 10,000 件まで | 
| 関数の持続時間 | サブミリ秒 |  最大 30 秒 (ビューワーリクエスト、ビューワーレスポンス) 最大 30 秒 (オリジンリクエスト、オリジンレスポンス)  | 
|  関数の最大メモリサイズ  | 2 MB |  128 MB (ビューワーリクエスト、ビューワーレスポンス) 10,240 MB (10 GB) (オリジンリクエスト、オリジンレスポンス) 詳細については、「[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)」を参照してください。  | 
| 関数コードと含まれるライブラリの最大サイズ | 10 KB |  50 MB (ビューワーリクエスト、ビューワーレスポンス) 50 MB (オリジンリクエスト、オリジンレスポンス)  | 
| ネットワークアクセス | いいえ | はい | 
| ファイルシステムへのアクセス | いいえ | はい | 
| リクエスト本文へのアクセス | いいえ | はい | 
| 位置情報とデバイスデータへのアクセス | はい |  いいえ (ビューワーリクエスト、ビューワーレスポンス) はい (オリジンリクエスト、オリジンレスポンス)  | 
| CloudFront でビルドとテストをすべて実施可能 | はい | いいえ | 
| 関数のログとメトリクス | はい | はい | 

# CloudFront Functions を使用してエッジでカスタマイズする
<a name="cloudfront-functions"></a>

CloudFront Functions を使用すると、JavaScript で軽量な関数を記述し、レイテンシーの影響を受けやすい CDN カスタマイズを大規模に実行できます。関数を使用して、CloudFront を通過するリクエストとレスポンスの操作、基本認証と認可の実行、エッジでの HTTP レスポンスの生成などを行うことができます。CloudFront Functions の runtime 環境は、起動時間が 1 ミリ秒未満、毎秒数百万のリクエストを処理するようにすぐにスケールでき、高い安全性を誇ります。CloudFront Functions は、CloudFront のネイティブ関数です。つまり、CloudFront 内でコードを完全に構築、テスト、デプロイできます。

CloudFront 関数を CloudFront ディストリビューションに関連付けると、CloudFront が CloudFront エッジロケーションでリクエストとレスポンスをインターセプトし、この関数に送ります。以下のイベントが発生したら、CloudFront Functions を呼び出すことができます。
+ CloudFront がビューワーからリクエストを受信したとき (ビューワーリクエスト)
+ CloudFront がビューワーにレスポンスを返す前 (ビューワーレスポンス)
+ TLS 接続の確立 (接続リクエスト) 中 - 相互 TLS (mTLS) 接続で現在利用可能です

CloudFront Functions の詳細については、以下のトピックを参照してください。

**Topics**
+ [チュートリアル: CloudFront Functions でシンプルな関数を作成する](functions-tutorial.md)
+ [チュートリアル: キー値を含む関数を作成する](functions-tutorial-kvs.md)
+ [関数コードを記述する](writing-function-code.md)
+ [関数を作成する](create-function.md)
+ [関数をテストする](test-function.md)
+ [関数を更新する](update-function.md)
+ [関数を発行する](publish-function.md)
+ [関数をディストリビューションに関連付ける](associate-function.md)
+ [Amazon CloudFront KeyValueStore](kvs-with-functions.md)

# チュートリアル: CloudFront Functions でシンプルな関数を作成する
<a name="functions-tutorial"></a>

このチュートリアルでは、CloudFront Functions の使用を開始する方法を示します。ビューワーを別の URL にリダイレクトし、さらにカスタムレスポンスヘッダーを返すシンプルな関数を作成できます。

**Contents**
+ [前提条件](#functions-tutorial-prerequisites)
+ [関数を作成する](#functions-tutorial-create)
+ [関数を検証する](#functions-tutorial-verify)

## 前提条件
<a name="functions-tutorial-prerequisites"></a>

CloudFront Functions の使用には、CloudFront ディストリビューションが必要です。アカウントをお持ちでない場合は、「[CloudFront 標準ディストリビューションの開始方法](GettingStarted.SimpleDistribution.md)」を参照してください。

## 関数を作成する
<a name="functions-tutorial-create"></a>

CloudFront コンソールを使用して、ビューワーを別の URL にリダイレクトし、さらにカスタムレスポンスヘッダーを返すシンプルな関数を作成できます。

**CloudFront 関数を作成するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) で CloudFront コンソールを開きます。

1. ナビゲーションペインで、**[関数]**、**[関数を作成]** の順に選択します。

1. **[関数を作成]** ページの **[名前]** に関数名 (*MyFunctionName* など) を入力します。

1. (オプション) **[説明]** に、関数の説明 (**Simple test function** など) を入力します。

1. **[ランタイム]** は、デフォルトで選択されている JavaScript バージョンのままにします。

1. [**関数の作成**] を選択してください。

1. 次の関数コードをコピーします。この関数コードは、ビューワーを別の URL にリダイレクトするほか、カスタムレスポンスヘッダーも返します。

   ```
   function handler(event) {
       // NOTE: This example function is for a viewer request event trigger. 
       // Choose viewer request for event trigger when you associate this function with a distribution. 
       var response = {
           statusCode: 302,
           statusDescription: 'Found',
           headers: {
               'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' },
               'location': { value: 'https://aws.amazon.com/cloudfront/' }
           }
       };
       return response;
   }
   ```

1. **[関数コード]** で、コードをコードエディタに貼り付け、デフォルトコードを置き換えます。

1. **[Save changes]** (変更の保存) をクリックします。

1. (オプション) 関数は発行前にテストすることもできます。このチュートリアルでは、関数のテスト方法は説明していません。詳細については、「[関数をテストする](test-function.md)」を参照してください。

1. **[発行]** タブを選択し、**[関数を発行]** を選択します。関数は、CloudFront ディストリビューションと関連付ける前に発行する必要があります。**

1. 次に、関数をディストリビューションまたはキャッシュ動作と関連付けることができます。*[MyFunctionName]* ページで、**[発行]** タブを選択します。
**警告**  
次の手順では、テストに使用するディストリビューションまたはキャッシュ動作を選択します。このテスト関数は、本番環境で使用するディストリビューションやキャッシュ動作には関連付けないでください。

1. [**Add association**] を選択します。

1. **[関連付け]** ダイアログボックスで、ディストリビューションまたはキャッシュ動作を選択します。**[イベントタイプ]** は、デフォルト値のままにします。

1. [**Add association**] を選択します。

   関連付けられているディストリビューションは、**[関連付けられているディストリビューション]** テーブルに表示されます。

1. 関連付けられたディストリビューションのデプロイが完了するまで数分待ちます。ディストリビューションのステータスを確認するには、**[関連づけられているディストリビューション]** テーブルでディストリビューションを選択し、**[ディストリビューションを表示]** を選択します。

   ディストリビューションのステータスが [**Deployed**] になったら、関数の動作を確認できます。

## 関数を検証する
<a name="functions-tutorial-verify"></a>

関数をデプロイしたら、ディストリビューションで機能することを検証できます。

**関数を検証するには**

1. ウェブブラウザで、ディストリビューションのドメイン名 (`https://d111111abcdef8.cloudfront.net` など) に移動します。

   関数はブラウザにリダイレクトを返すため、ブラウザは自動的に `https://aws.amazon.com/cloudfront/` に移動します。

1. コマンドラインウィンドウで、**curl** などのツールを使用してディストリビューションのドメイン名にリクエストを送信できます。

   ```
   curl -v https://d111111abcdef8.cloudfront.net/
   ```

   レスポンスに、リダイレクトレスポンス (`302 Found`) と、関数が追加したカスタムレスポンスヘッダーが表示されます。レスポンスは次の例のようになります。  
**Example**  

   ```
   curl -v https://d111111abcdef8.cloudfront.net/
   > GET / HTTP/1.1
   > Host: d111111abcdef8.cloudfront.net
   > User-Agent: curl/7.64.1
   > Accept: */*
   >
   < HTTP/1.1 302 Found
   < Server: CloudFront
   < Date: Tue, 16 Mar 2021 18:50:48 GMT
   < Content-Length: 0
   < Connection: keep-alive
   < Location: https://aws.amazon.com/cloudfront/
   < Cloudfront-Functions: generated-by-CloudFront-Functions
   < X-Cache: FunctionGeneratedResponse from cloudfront
   < Via: 1.1 3035b31bddaf14eded329f8d22cf188c.cloudfront.net (CloudFront)
   < X-Amz-Cf-Pop: PHX50-C2
   < X-Amz-Cf-Id: ULZdIz6j43uGBlXyob_JctF9x7CCbwpNniiMlmNbmwzH1YWP9FsEHg==
   ```

# チュートリアル: キー値を含む関数を作成する
<a name="functions-tutorial-kvs"></a>

このチュートリアルでは、CloudFront Function にキー値を含める方法を説明します。キー値はキーと値のペアの一部です。関数コードには (キーと値のペアの) 名前を含めます。関数を実行すると、CloudFront は名前を値に置き換えます。

キーと値のペアはキー値ストアに保存される変数です。関数で (ハードコードされた値の代わりに) キーを使用すると、関数の柔軟性が高まります。キーの値は、コードの変更をデプロイしなくても変更できます。キーと値のペアによって関数のサイズを小さくすることもできます。詳細については、「[Amazon CloudFront KeyValueStore](kvs-with-functions.md)」を参照してください。

**Contents**
+ [前提条件](#functions-kvs-tutorial-prerequisites)
+ [キー値ストアを作成する](#functions-kvs-tutorial-kvs-step)
+ [キー値ストアにキーと値のペアを追加する](#add-key-value-pairs-to-store)
+ [キー値ストアを関数に関連付ける](#functions-kvs-tutorial-functions-step)
+ [関数コードをテストして発行する](#test-and-publish-function-code)

## 前提条件
<a name="functions-kvs-tutorial-prerequisites"></a>

CloudFront Functions の関数とキー値ストアを初めて使用する場合は、「[チュートリアル: CloudFront Functions でシンプルな関数を作成する](functions-tutorial.md)」のチュートリアルに従うことをお勧めします。

そのチュートリアルを完了したら、このチュートリアルに従って、作成した関数を拡張できます。このチュートリアルでは、最初にキー値ストアを作成することをお勧めします。

## キー値ストアを作成する
<a name="functions-kvs-tutorial-kvs-step"></a>

まず、関数で使用するキー値ストアを作成します。

**キー値ストアを作成するには**

1. 関数に含めるキーと値のペアを計画します。キーの名前を書き留めます。1 つの関数で使用するキーと値のペアは、すべてが 1 つのキー値ストア内に存在する必要があります。

1. 作業の順序を決めます。次の 2 通りの方法があります。
   + キー値ストアを作成してキーと値のペアを追加します。次に、関数を作成 (または変更) し、キー名を組み込みます。
   + または、関数を作成 (または変更) し、使用したいキー名を組み込みます。次にキー値ストアを作成し、キーと値のペアを追加します。

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) で CloudFront コンソールを開きます。

1. ナビゲーションペインで、**[関数]**、**[KeyValueStores]** タブの順に選択します。

1. **[KeyValueStore を作成]** を選択し、以下のフィールドに入力します。
   + ストアの名前と、オプションの説明を入力します。
   + **[S3 URI]** は空白のままにします。このチュートリアルでは、キーと値のペアを手動で入力します。

1. **[作成]** を選びます。新しいキーバリューストアの詳細ページが表示されます。このページには、現在空欄の **[キーと値のペア]** セクションがあります。

## キー値ストアにキーと値のペアを追加する
<a name="add-key-value-pairs-to-store"></a>

次に、先ほど作成したキー値ストアにキーと値のペアのリストを手動で追加します。

**キー値ストアにキーと値のペアを追加するには**

1. **[キーと値のペア]** セクションで、**[キーと値のペアを追加]** を選択します。

1. **[ペアを追加]** を選択し、キーと値を入力します。チェックマークをオンにして変更を確認します。さらに追加するには、このステップを繰り返します。

1. 完了したら、**[変更を保存]** を選択してキー値ストアにキーと値のペアを保存します。確認ダイアログボックスで、**[完了]** を選択します。

これで、キーと値のペアのグループがキー値ストアに含まれました。



## キー値ストアを関数に関連付ける
<a name="functions-kvs-tutorial-functions-step"></a>

これで、キー値ストアが作成されました。また、キー値ストアのキー名を含む関数を作成または変更しました。これでキー値ストアと関数を関連付けることができます。その関連付けは関数内から作成します。

**キー値ストアを関数に関連付けるには**

1. ナビゲーションペインで、**[関数]** を選択します。デフォルトでは、**[関数]** タブが一番上に表示されます。

1. 関数名を選択し、**[関連付けられている KeyValueStore]** セクションで、**[既存の KeyValueStore を関連付ける]** を選択します。

1. キー値ストアを選択し、**[KeyValueStore を関連付ける]** を選択します。

**注記**  
各関数に関連付けることができるキー値ストアは 1 つだけです。

## 関数コードをテストして発行する
<a name="test-and-publish-function-code"></a>

キー値ストアを関数に関連付けると、関数コードをテストして発行できます。以下を行う場合を含め、関数コードを変更するたびに必ずテストする必要があります。
+ キー値ストアを関数に関連付ける
+ 関数およびキー値ストアを変更して、新しいキーと値のペアを含めます。
+ キーと値のペアの値を変更する

**関数コードをテストして発行するには**

1. 関数をテストする方法については、「[関数をテストする](test-function.md)」を参照してください。`DEVELOPMENT` ステージで関数のテストを選択するようにしてください。

1. 関数を (新規または更新されたキーと値のペアと共に) `LIVE` 環境で使用する準備が整ったら、関数を発行します。

   発行すると、CloudFront は関数のバージョンを `DEVELOPMENT` ステージからライブステージにコピーします。関数には新しいコードが含まれ、キー値ストアに関連付けられます。(ライブステージで関連付けを再度実行する必要はありません)。

   関数を発行する方法については、「[関数を発行する](publish-function.md)」を参照してください。

# 関数コードを記述する
<a name="writing-function-code"></a>

CloudFront Functions を使用すると、大規模でレイテンシーの影響を受けやすい CDN カスタマイズのための軽量な関数を JavaScript で記述できます。関数コードを使用して、CloudFront を通過するリクエストとレスポンスの操作、基本認証と認可の実行、エッジでの HTTP レスポンスの生成などを行うことができます。

CloudFront Functions の関数コードを記述する場合は、以下のトピックも参考になります。コード例については、「[CloudFront の CloudFront Functions の例](service_code_examples_cloudfront_functions_examples.md)」と GitHub の「[amazon-cloudfront-functions repository](https://github.com/aws-samples/amazon-cloudfront-functions)」を参照してください。

**Topics**
+ [関数の目的を決定する](function-code-choose-purpose.md)
+ [イベントの構造](functions-event-structure.md)
+ [JavaScript ランタイムの機能](functions-javascript-runtime-features.md)
+ [キーバリューストアのヘルパーメソッド](functions-custom-methods.md)
+ [オリジン変更のヘルパーメソッド](helper-functions-origin-modification.md)
+ [CloudFront SaaS Manager プロパティのヘルパーメソッド](saas-specific-logic-function-code.md)
+ [async および await を使用します。](async-await-syntax.md)
+ [CloudFront Functions の CWT サポート](cwt-support-cloudfront-functions.md)
+ [一般的なヘルパーメソッド](general-helper-methods.md)

# 関数の目的を決定する
<a name="function-code-choose-purpose"></a>

関数コードを記述する前に、関数の目的を決めます。CloudFront Functions の関数の大半は、次のいずれかを目的としています。

**Topics**
+ [ビューワーリクエストイベントタイプの HTTP リクエストの変更](#function-code-modify-request)
+ [ビューワーリクエストイベントタイプで HTTP レスポンスを生成する](#function-code-generate-response)
+ [ビューワーレスポンスイベントタイプの HTTP レスポンスの変更](#function-code-modify-response)
+ [接続リクエストイベントタイプの mTLS 接続を検証する](#function-code-connection-request)
+ [関連情報](#related-information-cloudfront-functions-purpose)

関数の目的にかかわらず、`handler` はあらゆる関数のエントリポイントです。CloudFront から関数に送られる `event` という単一の引数を使います。`event` は、HTTP リクエスト表記の JSON オブジェクトです (関数が HTTP レスポンスを変更する場合は、レスポンス)。

## ビューワーリクエストイベントタイプの HTTP リクエストの変更
<a name="function-code-modify-request"></a>

関数は、CloudFront がビューワー (クライアント) から受信する HTTP リクエストを変更し、変更されたリクエストを CloudFront に返して処理を続行できます。たとえば、関数コードで[キャッシュキー](understanding-the-cache-key.md)を正規化したり、リクエストヘッダーを変更したりできます。

HTTP リクエストを変更する関数を作成して発行する場合は、必ず*ビューワーリクエスト*イベントタイプの関連付けを追加してください。詳細については、「[関数を作成する](functions-tutorial.md#functions-tutorial-create)」を参照してください。これにより、CloudFront がビューワーからリクエストを受信するたびに、リクエストされたオブジェクトが CloudFront キャッシュにあるかどうかをチェックする前に、関数が実行されます。

**Example 例**  
次の擬似コードは、HTTP リクエストを変更する関数の構造を示しています。  

```
function handler(event) {
    var request = event.request;

    // Modify the request object here.

    return request;
}
```
この関数は、変更された `request` オブジェクトを CloudFront に返します。CloudFront は、CloudFront キャッシュでキャッシュヒットがないかチェックし、必要に応じてリクエストをオリジンに送信することで、返されたリクエストの処理を続行します。

## ビューワーリクエストイベントタイプで HTTP レスポンスを生成する
<a name="function-code-generate-response"></a>

関数は、エッジで HTTP レスポンスを生成し、キャッシュされたレスポンスまたは CloudFront によるそれ以降の処理をチェックすることなく、ビューワー (クライアント) に直接返すことができます。たとえば、関数コードは、リクエストを新しい URL にリダイレクトしたり、承認をチェックして、`401` や `403` レスポンスを非承認リクエストに返す場合があります。

HTTP レスポンスを生成する関数を作成する場合は、必ず*ビューワーリクエスト*イベントタイプを選択してください 。つまりこの関数は、CloudFront がビューワーからリクエストを受信するたびに、CloudFront がリクエストの処理を行う前に実行されます。

**Example 例**  
次の擬似コードは、HTTP 応答を生成する関数の構造を示しています。  

```
function handler(event) {
    var request = event.request;

    var response = ...; // Create the response object here,
                        // using the request properties if needed.

    return response;
}
```
この関数は、CloudFront に `response` オブジェクトを返します。CloudFront はこのオブジェクトを、CloudFront キャッシュをチェックしたり、オリジンにリクエストを送信したりすることなく、すぐにビューワーに戻します。

## ビューワーレスポンスイベントタイプの HTTP レスポンスの変更
<a name="function-code-modify-response"></a>

関数は、レスポンスが CloudFront キャッシュとオリジンのどちらから来たかに関係なく、CloudFront がビューワー (クライアント) に送信する前に HTTP レスポンスを変更できます。例えば、関数コードでレスポンスヘッダー、ステータスコード、本文のコンテンツを追加または変更する場合があります。

HTTP レスポンスを変更する関数を作成する場合は、必ず*ビューワーレスポンス*イベントタイプを選択してください。つまり関数は、レスポンスが CloudFront キャッシュまたはオリジンのどちらから来たかに関係なく、CloudFront がビューワーにレスポンスを返す前に実行されます。

**Example 例**  
次の擬似コードは、HTTP レスポンスを変更する関数の構造を示しています。  

```
function handler(event) {
    var request = event.request;
    var response = event.response;

    // Modify the response object here,
    // using the request properties if needed.

    return response;
}
```
この関数は変更された `response` オブジェクトを CloudFront に返し、CloudFront はこれをすぐにビューワーに返します。

## 接続リクエストイベントタイプの mTLS 接続を検証する
<a name="function-code-connection-request"></a>

接続関数は、カスタム検証および認証ロジックを提供するために TLS 接続中に実行される CloudFront Functions の一種です。接続関数は現在、相互 TLS (mTLS) 接続で使用できます。ここでは、クライアント証明書を検証し、標準証明書の検証を超えてカスタム認証ロジックを実装できます。接続関数は TLS ハンドシェイクプロセス中に実行され、証明書プロパティ、クライアント IP アドレス、または他の条件に基づいて接続を許可または拒否できます。

接続関数を作成して公開した後、mTLS が有効なディストリビューションとの*接続リクエスト*イベントタイプの関連付けを追加してください。これにより、クライアントが CloudFront との mTLS 接続を確立しようとするたびに関数が実行されるようになります。

**Example**  
次の擬似コードは、接続関数の構造を示しています。  

```
function connectionHandler(connection) {
    // Validate certificate and connection properties here.
    
    if (/* validation passes */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```
関数はヘルパーメソッドを使用して、接続を許可または拒否するかどうかを決定します。ビューワーリクエストおよびビューワーレスポンス関数とは異なり、接続関数は HTTP リクエストまたはレスポンスを変更できません。

## 関連情報
<a name="related-information-cloudfront-functions-purpose"></a>

CloudFront Functions の操作の詳細については、以下のトピックを参照してください。
+ [イベントの構造](functions-event-structure.md)
+ [JavaScript ランタイムの機能](functions-javascript-runtime-features.md)
+ [CloudFront Functions の例 ](service_code_examples_cloudfront_functions_examples.md)
+ [エッジ関数に対する制限](edge-functions-restrictions.md)

# CloudFront Functions のイベント構造
<a name="functions-event-structure"></a>

CloudFront Functions は、関数を実行するときに `event` オブジェクトを関数コードに入力として渡します。[関数をテスト](test-function.md)するときは、`event` オブジェクトを作成し、関数に渡します。関数をテストするために `event` オブジェクトを作成する場合は、`distributionDomainName` オブジェクト内の `distributionId`、`requestId`、`context` フィールドを省略できます。ヘッダーの名前が小文字であることを確認してください (CloudFront Functions が本番環境で関数に渡す `event` オブジェクトはすべて該当します)。

次に、このイベントオブジェクトの構造の概要を示します。

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

詳細については、以下の各トピックを参照してください。

**Topics**
+ [バージョンフィールド](#functions-event-structure-version)
+ [コンテキストオブジェクト](#functions-event-structure-context)
+ [接続イベントの構造](#functions-event-structure-connection)
+ [ビューワーオブジェクト](#functions-event-structure-viewer)
+ [リクエストオブジェクト](#functions-event-structure-request)
+ [レスポンスオブジェクト](#functions-event-structure-response)
+ [ステータスコードと本文](#functions-event-structure-status-body)
+ [クエリ文字列、ヘッダー、または Cookie の構造](#functions-event-structure-query-header-cookie)
+ [レスポンスオブジェクトの例](#functions-response-structure-example)
+ [イベントオブジェクトの例](#functions-event-structure-example)

## バージョンフィールド
<a name="functions-event-structure-version"></a>

`version` フィールドには、CloudFront Functions イベントオブジェクトのバージョンを指定する文字列が含まれます。現在のバージョンは `1.0` です。

## コンテキストオブジェクト
<a name="functions-event-structure-context"></a>

`context` オブジェクトには、イベントに関するコンテキスト情報が含まれます。次のフィールドが含まれています。

**`distributionDomainName`**  
イベントに関連付けられた標準ディストリビューションの CloudFront ドメイン名 (例: d111111abcdef8.cloudfront.net)。  
`distributionDomainName` フィールドは、関数が標準ディストリビューションに対して呼び出された場合にのみ表示されます。

**`endpoint`**  
イベントに関連付けられた接続グループの CloudFront ドメイン名 (例: d111111abcdef8.cloudfront.net)。  
`endpoint` フィールドは、関数がマルチテナントディストリビューションに対して呼び出された場合にのみ表示されます。

**`distributionId`**  
イベントに関連付けられたディストリビューションの ID (例: EDFDVBD6EXAMPLE) 。

**`eventType`**  
イベントタイプ (`viewer-request` または`viewer-response`)。

**`requestId`**  
CloudFront リクエスト (およびそれに関連付けられたレスポンス) を一意に識別する文字列。

## 接続イベントの構造
<a name="functions-event-structure-connection"></a>

接続関数は、ビューワー関数とは異なるイベント構造を受け取ります。接続イベントの構造とレスポンス形式の詳細については、「[CloudFront Connection Function を関連付ける](connection-functions.md)」を参照してください。

## ビューワーオブジェクト
<a name="functions-event-structure-viewer"></a>

`viewer` オブジェクトには、リクエストを送信したビューワー (クライアント) の IP アドレスを値とする `ip` フィールドが含まれています。ビューワーリクエストが HTTP プロキシまたはロードバランサーを通して来た場合、値はプロキシまたはロードバランサーの IP アドレスです。

## リクエストオブジェクト
<a name="functions-event-structure-request"></a>

`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 つのフィールドが含まれます。ヘッダー名は、イベントオブジェクトでは ASCII 小文字に変換されます。また、関数コードで追加する場合、ヘッダー名を ASCII 小文字にする必要があります。CloudFront Functions がイベントオブジェクトを HTTP リクエストに変換し直すと、ヘッダー名の各単語の最初の文字が ASCII 文字の場合は大文字になります。CloudFront Functions は、ヘッダー名の非 ASCII 記号には変更を適用しません。例えば、関数内では `TÈst-header` は `tÈst-header` になります。非 ASCII 記号 `È` は変更されません。  
各単語はハイフン (`-`) で区切られます。例えば、関数コードが `example-header-name` という名前のヘッダーを追加した場合、CloudFront がこれを HTTP リクエストで `Example-Header-Name` に変換します。

**`cookies`**  
リクエスト (`Cookie` ヘッダー) の Cookie を表すオブジェクト。  
`cookies` オブジェクトには、リクエストの Cookie 1 つにつき 1 つのフィールドが含まれます。

クエリ文字列、ヘッダーおよび Cookie の構造の詳細については、「[クエリ文字列、ヘッダー、または Cookie の構造](#functions-event-structure-query-header-cookie)」を参照してください。

`event` オブジェクトの例については、「[イベントオブジェクトの例](#functions-event-structure-example)」を参照してください。

## レスポンスオブジェクト
<a name="functions-event-structure-response"></a>

`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` コンテンツ。

変更されたステータスコードと本文の内容の詳細については、[ステータスコードと本文](#functions-event-structure-status-body) を参照してください。

ヘッダーと Cookie の構造の詳細については、「[クエリ文字列、ヘッダー、または Cookie の構造](#functions-event-structure-query-header-cookie)」を参照してください。

`response` オブジェクトの例については、「[レスポンスオブジェクトの例](#functions-response-structure-example)」を参照してください。

## ステータスコードと本文
<a name="functions-event-structure-status-body"></a>

CloudFront Functions を使用して、ビューワーのレスポンスステータスコードを更新したり、レスポンス本文すべてを新しく置き換えたり、レスポンス本文を削除したりできます。CloudFront キャッシュまたはオリジンからのレスポンスを評価した後でビューワーのレスポンスを更新する一般的なシナリオには、次のようなものがあります。
+ ステータスを変更して HTTP 200 ステータスコードを設定し、ビューワーに返す静的な本文コンテンツを作成する。
+ HTTP 301 または 302 ステータスコードを設定して、ユーザーを別のウェブサイトにリダイレクトする。
+ ビューワーレスポンスの本文を配信するか削除するかを決定します。

**注記**  
オリジンが 400 以上の HTTP エラーを返した場合、CloudFront Functions は実行されません。詳細については、「[すべてのエッジ機能に対する制限](edge-function-restrictions-all.md)」を参照してください。

HTTP レスポンスを使用する場合、CloudFront Functions は、レスポンス本文にアクセスできません。必要な値に設定することで本文コンテンツを置き換えたり、値を空に設定することで本文を削除したりできます。関数内の本文フィールドを更新しない場合は、CloudFront キャッシュまたはオリジンによって返された元の本文がビューワーに返されます。

**ヒント**  
CloudFront Functions を使用して本文を置き換える場合は、`content-encoding`、`content-type`、`content-length` などの対応するヘッダーを新しい本文のコンテンツに合わせてください。  
たとえば、CloudFront オリジンまたはキャッシュが `content-encoding: gzip` を返したが、ビューワーレスポンス関数が本文をプレーンテキストに設定した場合、関数は `content-encoding` と `content-type` ヘッダーもそれに応じて変更する必要があります。

CloudFront Functions が 400 以上の HTTP エラーを返すように設定されている場合、ビューワーには同じステータスコードに対して指定した[カスタムエラーページ](creating-custom-error-pages.md)は表示されません。

## クエリ文字列、ヘッダー、または Cookie の構造
<a name="functions-event-structure-query-header-cookie"></a>

クエリ文字列、ヘッダー、Cookie は同じ構造を共有します。クエリ文字列は、リクエストに表示される場合があります。ヘッダーは、リクエストとレスポンスに表示されます。Cookie は、リクエストとレスポンスに表示されます。

クエリ文字列、ヘッダーおよび Cookie はすべて、親 `querystring`、`headers`、`cookies`オブジェクトで一意のフィールドです。フィールド名は、クエリ文字列、ヘッダー、または Cookie の名前です。各フィールドには、クエリ文字列、ヘッダー、Cookie の値を持つ `value` プロパティが含まれます。

**Contents**
+ [クエリ文字列値またはクエリ文字列オブジェクト](#functions-event-structure-query)
+ [ヘッダーに関する特別な考慮事項](#functions-event-structure-headers)
+ [重複するクエリ文字列、ヘッダー、Cookie (`multiValue` 配列)](#functions-event-structure-multivalue)
+ [Cookie 属性](#functions-event-structure-cookie-attributes)

### クエリ文字列値またはクエリ文字列オブジェクト
<a name="functions-event-structure-query"></a>

関数は、クエリ文字列オブジェクトに加えてクエリ文字列値を返すことができます。クエリ文字列値を使用して、クエリ文字列パラメータを任意のカスタム順序で配置できます。

**Example 例**  
関数コードでクエリ文字列を変更するには、次のようなコードを使用します。  

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

### ヘッダーに関する特別な考慮事項
<a name="functions-event-structure-headers"></a>

ヘッダーのみの場合、ヘッダー名がイベントオブジェクトで小文字に変換されます。また、関数コードで追加する場合は、ヘッダー名を小文字にする必要があります。CloudFront Functions がイベントオブジェクトを HTTP リクエストまたはレスポンスに変換し直すと、ヘッダー名の各単語の最初の文字が大文字になります。各単語はハイフン (`-`) で区切られます。例えば、関数コードが `example-header-name` という名前のヘッダーを追加した場合、CloudFront がこれを HTTP リクエストまたはレスポンスの `Example-Header-Name` に変換します。

**Example 例**  
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` 配列)
<a name="functions-event-structure-multivalue"></a>

HTTP リクエストまたはレスポンスには、同じ名前のクエリ文字列、ヘッダー、Cookie が含まれることがあります。この場合、重複するクエリ文字列、ヘッダー、Cookie は `request` または `response` オブジェクトの 1 つのフィールドに折りたたまれていますが、このフィールドには `multiValue` という名前の追加のプロパティが含まれます。`multiValue` プロパティには、重複するクエリ文字列、ヘッダー、Cookie の各値を含む配列が含まれます。

**Example 例**  
以下の `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 は以下のルールを使用して変更を適用します。

1. `multiValue` 配列が存在し、変更がある場合は、その変更が適用されます。`value` プロパティの最初の要素は無視されます。

1. それ以外の場合は、`value` プロパティへの変更が適用され、それ以降の値 (存在する場合) は変更されません。

この `multiValue` プロパティは、前の例に示すように、HTTP リクエストまたはレスポンスに同じ名前の重複するクエリ文字列、ヘッダー、Cookie のいずれかが含まれている場合にのみ使用されます。ただし、1 つのクエリ文字列、ヘッダー、または Cookie に複数の値がある場合、`multiValue` プロパティは使用されません。

**Example 例**  
3 つの値を含む 1 つの `Accept` ヘッダーを持つリクエストについて考えてみます。  

```
Accept: application/json, application/xml, text/html
```
このヘッダーは、`request` オブジェクトで次のように表されます。  

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

### Cookie 属性
<a name="functions-event-structure-cookie-attributes"></a>

HTTP レスポンスの `Set-Cookie` ヘッダーでは、ヘッダーに Cookie の名前と値のペア、および必要に応じてセミコロンで区切られた属性のセットが含まれます。

**Example 例**  

```
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"
}
```

## レスポンスオブジェクトの例
<a name="functions-response-structure-example"></a>

次の例は、本文がビューワーレスポンス関数に置き換えられた `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>"
    }
  }
}
```

## イベントオブジェクトの例
<a name="functions-event-structure-example"></a>

以下は、完全な `event` オブジェクトの例です。これは、マルチテナントディストリビューションではなく、標準ディストリビューションの呼び出しの例です。マルチテナントディストリビューションの場合、`endpoint` フィールドは `distributionDomainName` の代わりに使用されます。`endpoint` の値は、イベントに関連付けられている接続グループの CloudFront ドメイン名 (d111111abcdef8.cloudfront.net など) です。

**注記**  
`event` オブジェクトは関数への入力です。関数は、`request` オブジェクト全体ではなく、`response` または `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"
                    }
                ]
            }
        }
    }
}
```

# CloudFront Functions の JavaScript ランタイムの機能
<a name="functions-javascript-runtime-features"></a>

CloudFront Functions の JavaScript ランタイム環境は [ ECMAScript (ES) バージョン 5.1](https://www.ecma-international.org/ecma-262/5.1/) に準拠しており、ES バージョン 6～12 の一部の機能をサポートしています。

最新の機能を利用するには、JavaScript ランタイム 2.0 を使用することをお勧めします。

JavaScript ランタイム 2.0 の機能には、1.0 と比較して以下の変更があります。
+ バッファモジュールメソッドが利用可能です。
+ 以下の非標準の文字列プロトタイプメソッドは使用できません。
  + `String.prototype.bytesFrom()`
  + `String.prototype.fromBytes()`
  + `String.prototype.fromUTF8()`
  + `String.prototype.toBytes()`
  + `String.prototype.toUTF8()`
+ 暗号モジュールには次の変更があります。
  + `hash.digest()` - エンコーディングを指定しない場合、戻り型は `Buffer` に変更されます。
  + `hmac.digest()` - エンコーディングを指定しない場合、戻り型は `Buffer` に変更されます。
+ その他の新しい機能の詳細については、「[CloudFront Functions の JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md)」を参照してください。

**Topics**
+ [JavaScript ランタイム 1.0 の機能](functions-javascript-runtime-10.md)
+ [JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md)

# CloudFront Functions の JavaScript ランタイム 1.0 の機能
<a name="functions-javascript-runtime-10"></a>

CloudFront Functions の JavaScript ランタイム環境は [ ECMAScript (ES) バージョン 5.1](https://262.ecma-international.org/5.1/) に準拠しており、ES バージョン 6～9 の一部の機能をサポートしています。また、ES 仕様に含まれない非標準メソッドも提供しています。

次のトピックでは、サポートされるすべての言語機能の一覧を示します。

**Topics**
+ [主要機能](#writing-functions-javascript-features-core)
+ [プリミティブオブジェクト](#writing-functions-javascript-features-primitive-objects)
+ [ビルトインオブジェクト](#writing-functions-javascript-features-builtin-objects)
+ [エラーのタイプ](#writing-functions-javascript-features-error-types)
+ [Globals](#writing-functions-javascript-features-globals)
+ [ビルトインモジュール](#writing-functions-javascript-features-builtin-modules)
+ [制限された機能](#writing-functions-javascript-features-restricted-features)

## 主要機能
<a name="writing-functions-javascript-features-core"></a>

ES の次の主要機能がサポートされています。

**Types]**  
すべての ES 5.1 タイプでサポートされています。これには、ブール値、数値、文字列、オブジェクト、配列、関数、関数コンストラクタ、正規表現が含まれます。

**演算子**  
すべての ES 5.1 演算子でサポートされています。  
ES 7 指数演算子 (`**`) がサポートされています。

**ステートメント**  
`const` および `let` ステートメントはサポートされていません。
次の ES 5.1 ステートメントがサポートされています。  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
+ ラベル付きステートメント

**リテラル**  
ES 6 テンプレートリテラル (複数行の文字列、式の補間、および入れ子テンプレート) がサポートされています。

**関数**  
すべての ES 5.1 機能がサポートされています。  
ES 6 のアロー関数、ES 6 のレストパラメータ (残余因数) 構文がサポートされています。

**Unicode**  
ソーステキストおよび文字列リテラルには、Unicode でエンコードされた文字を含めることができます。6 文字の Unicode エスケープシーケンス (コードポイント、例: `\uXXXX`) もサポートされています。

**Strict モード**  
関数は Strict モードで動作するため、関数コードに `use strict` ステートメントを追加する必要はありません。これは変更できません。

## プリミティブオブジェクト
<a name="writing-functions-javascript-features-primitive-objects"></a>

以下の ES プリミティブオブジェクトがサポートされています。

**オブジェクト**  
オブジェクトについて以下の ES 5.1 メソッドがサポートされています。  
+ `create` (プロパティリストなし)
+ `defineProperties`
+ `defineProperty`
+ `freeze`
+ `getOwnPropertyDescriptor`
+ `getOwnPropertyNames`
+ `getPrototypeOf`
+ `hasOwnProperty`
+ `isExtensible`
+ `isFrozen`
+ `prototype.isPrototypeOf`
+ `isSealed`
+ `keys`
+ `preventExtensions`
+ `prototype.propertyIsEnumerable`
+ `seal`
+ `prototype.toString`
+ `prototype.valueOf`
オブジェクトについて以下の ES 6 メソッドがサポートされています。  
+ `assign`
+ `is`
+ `prototype.setPrototypeOf`
オブジェクトについて以下の ES 8 メソッドがサポートされています。  
+ `entries`
+ `values`

**文字列**  
文字列について以下の ES 5.1 メソッドがサポートされています。  
+ `fromCharCode`
+ `prototype.charAt`
+ `prototype.concat`
+ `prototype.indexOf`
+ `prototype.lastIndexOf`
+ `prototype.match`
+ `prototype.replace`
+ `prototype.search`
+ `prototype.slice`
+ `prototype.split`
+ `prototype.substr`
+ `prototype.substring`
+ `prototype.toLowerCase`
+ `prototype.trim`
+ `prototype.toUpperCase`
文字列について以下の ES 6 メソッドがサポートされています。  
+ `fromCodePoint`
+ `prototype.codePointAt`
+ `prototype.endsWith`
+ `prototype.includes`
+ `prototype.repeat`
+ `prototype.startsWith`
文字列について以下の ES 8 メソッドがサポートされています。  
+ `prototype.padStart`
+ `prototype.padEnd`
文字列について以下の ES 9 メソッドがサポートされています。  
+ `prototype.trimStart`
+ `prototype.trimEnd`
文字列について以下の非標準メソッドがサポートされています。  
+ `prototype.bytesFrom(array | string, encoding)`

  オクテット列またはエンコードされた文字列からバイト文字列を作成します。文字列エンコーディングオプションは `hex`、`base64`、`base64url`です。
+ `prototype.fromBytes(start[, end])`

  バイト文字列から Unicode 文字列を作成します。各バイトは、対応する Unicode コードポイントで置き換えられます。
+ `prototype.fromUTF8(start[, end])`

  UTF-8 でエンコードされたバイト文字列から Unicode 文字列を作成します。エンコーディングが正しくない場合は、`null` が返されます。
+ `prototype.toBytes(start[, end])`

  Unicode 文字列からバイト文字列を作成します。すべての文字は [0,255] の範囲内にある必要があります。そうでない場合は、`null` が返されます。
+ `prototype.toUTF8(start[, end])`

  Unicode 文字列から UTF-8 でエンコードされたバイト文字列を作成します。

**数値**  
番号に関するすべての ES 5.1 メソッドがサポートされています。  
番号について以下の ES 6 メソッドがサポートされています。  
+ `isFinite`
+ `isInteger`
+ `isNaN`
+ `isSafeInteger`
+ `parseFloat`
+ `parseInt`
+ `prototype.toExponential`
+ `prototype.toFixed`
+ `prototype.toPrecision`
+ `EPSILON`
+ `MAX_SAFE_INTEGER`
+ `MAX_VALUE`
+ `MIN_SAFE_INTEGER`
+ `MIN_VALUE`
+ `NEGATIVE_INFINITY`
+ `NaN`
+ `POSITIVE_INFINITY`

## ビルトインオブジェクト
<a name="writing-functions-javascript-features-builtin-objects"></a>

ES の以下のビルトインオブジェクトがサポートされています。

**Math**  
ES 5.1 のすべての Math メソッドがサポートされています。  
CloudFront Functions runtime 環境では、`Math.random()` 実装に、関数が実行されたときのタイムスタンプがシードされた OpenBSD `arc4random` を使用します。
以下の ES 6 Math メソッドがサポートされています。  
+ `acosh`
+ `asinh`
+ `atanh`
+ `cbrt`
+ `clz32`
+ `cosh`
+ `expm1`
+ `fround`
+ `hypot`
+ `imul`
+ `log10`
+ `log1p`
+ `log2`
+ `sign`
+ `sinh`
+ `tanh`
+ `trunc`
+ `E`
+ `LN10`
+ `LN2`
+ `LOG10E`
+ `LOG2E`
+ `PI`
+ `SQRT1_2`
+ `SQRT2`

**日付**  
すべての ES 5.1 の `Date` 機能がサポートされています。  
セキュリティ上の理由から、`Date` は、単一の関数実行の有効期間中、常に同じ値 (関数の開始時間) を返します。詳細については、「[制限された機能](#writing-functions-javascript-features-restricted-features)」を参照してください。

**関数**  
`apply`、`bind`、`call` メソッドがサポートされています。  
関数コンストラクタはサポートされていません。

**正規表現**  
すべての ES 5.1 の正規表現機能がサポートされています。正規表現言語は Perl 互換です。ES 9 の名前付きキャプチャグループがサポートされています。

**JSON**  
`parse`、`stringify` を含むすべての ES 5.1 JSON 機能がサポートされています。

**配列**  
配列について以下の ES 5.1 メソッドがサポートされています。  
+ `isArray`
+ `prototype.concat`
+ `prototype.every`
+ `prototype.filter`
+ `prototype.forEach`
+ `prototype.indexOf`
+ `prototype.join`
+ `prototype.lastIndexOf`
+ `prototype.map`
+ `prototype.pop`
+ `prototype.push`
+ `prototype.reduce`
+ `prototype.reduceRight`
+ `prototype.reverse`
+ `prototype.shift`
+ `prototype.slice`
+ `prototype.some`
+ `prototype.sort`
+ `prototype.splice`
+ `prototype.unshift`
配列について以下の ES 6 メソッドがサポートされています。  
+ `of`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.find`
+ `prototype.findIndex`
配列について以下の ES 7 メソッドがサポートされています。  
+ `prototype.includes`

**型付き配列**  
以下の ES 6 型付き配列がサポートされています。  
+ `Int8Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Int16Array`
+ `Uint16Array`
+ `Int32Array`
+ `Uint32Array`
+ `Float32Array`
+ `Float64Array`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.join`
+ `prototype.set`
+ `prototype.slice`
+ `prototype.subarray`
+ `prototype.toString`

**ArrayBuffer**  
`ArrayBuffer` について以下のメソッドがサポートされています。  
+ `prototype.isView`
+ `prototype.slice`

**promise**  
promise について以下のメソッドがサポートされています。  
+ `reject`
+ `resolve`
+ `prototype.catch`
+ `prototype.finally`
+ `prototype.then`

**Crypto**  
暗号モジュールは、標準のハッシュおよびハッシュベースのメッセージ認証コード (HMAC) ヘルパーを提供します。`require('crypto')` を使用してモジュールをロードできます。モジュールは、Node.js の相対物とまったく同じように動作する以下のメソッドを公開します。  
+ `createHash(algorithm)`
+ `hash.update(data)`
+ `hash.digest([encoding])`
+ `createHmac(algorithm, secret key)`
+ `hmac.update(data)`
+ `hmac.digest([encoding])`
詳細については、「ビルトインモジュールセクション」の「[Crypto (ハッシュと HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)」を参照してください。

**コンソール**  
これはデバッグ用のヘルパーオブジェクトです。ログメッセージを記録するための `log()` メソッドのみサポートしています。  
CloudFront Functions は、`console.log('a', 'b')` などのカンマ構文をサポートしていません。代わりに、`console.log('a' + ' ' + 'b')` 形式を使用してください。

## エラーのタイプ
<a name="writing-functions-javascript-features-error-types"></a>

以下のエラーオブジェクトがサポートされています。
+ `Error`
+ `EvalError`
+ `InternalError`
+ `MemoryError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals"></a>

`globalThis` オブジェクトはサポートされています。

以下の ES 5.1 グローバル関数がサポートされています。
+ `decodeURI`
+ `decodeURIComponent`
+ `encodeURI`
+ `encodeURIComponent`
+ `isFinite`
+ `isNaN`
+ `parseFloat`
+ `parseInt`

以下のグローバル定数がサポートされています。
+ `NaN`
+ `Infinity`
+ `undefined`

## ビルトインモジュール
<a name="writing-functions-javascript-features-builtin-modules"></a>

以下のビルトインモジュールがサポートされています。

**Topics**
+ [Crypto (ハッシュと HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)
+ [クエリ文字列](#writing-functions-javascript-features-builtin-modules-query-string)

### Crypto (ハッシュと HMAC)
<a name="writing-functions-javascript-features-builtin-modules-crypto"></a>

暗号モジュール (`crypto`) は、標準のハッシュおよびハッシュベースのメッセージ認証コード (HMAC) ヘルパーを提供します。`require('crypto')` を使用してモジュールをロードできます。このモジュールは、Node.js の相対物とまったく同じように動作する以下のメソッドを提供します。

**ハッシュメソッド**

`crypto.createHash(algorithm)`  
ハッシュオブジェクトを作成して返します。このハッシュオブジェクトは、指定されたアルゴリズム (`md5`、`sha1`、`sha256` のいずれか) を使用してハッシュダイジェストの生成に使用できます。

`hash.update(data)`  
指定された `data` を使用してハッシュコンテンツを更新します。

`hash.digest([encoding])`  
`hash.update()` を使用して渡されたすべてのデータのダイジェストを計算します。エンコードは `hex`、`base64`、`base64url` のいずれかを使用します。

**HMAC メソッド**

`crypto.createHmac(algorithm, secret key)`  
指定された `algorithm` と `secret key` を使用する HMAC オブジェクトを作成して返します。アルゴリズムは `md5`、`sha1`、`sha256` のいずれかを使用します。

`hmac.update(data)`  
指定された `data` を使用して HMAC コンテンツを更新します 。

`hmac.digest([encoding])`  
`hmac.update()` を使用して渡されたすべてのデータのダイジェストを計算します。エンコードは `hex`、`base64`、`base64url` のいずれかを使用します。

### クエリ文字列
<a name="writing-functions-javascript-features-builtin-modules-query-string"></a>

**注記**  
[CloudFront Functions イベントオブジェクト](functions-event-structure.md)は、URL クエリ文字列を自動的に解析します。つまり、ほとんどの場合、このモジュールを使用する必要はありません。

クエリ文字列モジュール (`querystring`) は、URL クエリ文字列を解析および書式設定するためのメソッドを提供します。`require('querystring')` を使用してモジュールをロードできます。このモジュールは、以下のメソッドを提供します。

`querystring.escape(string)`  
URL は `string` をエンコードし、エスケープしたクエリ文字列を返します。このメソッドは `querystring.stringify()` で使用するため、直接使用しないでください。

`querystring.parse(string[, separator[, equal[, options]]])`  
クエリ文字列 (`string`) を解析し、オブジェクトを返します。  
`separator` パラメータは、クエリ文字列のキーと値のペアを区切る substring です。デフォルトでは、`&` です。  
`equal` パラメータは、クエリ文字列のキーと値を区切る substring です。デフォルトでは、`=` です。  
`options` パラメータは、以下のキーを持つオブジェクトです。    
`decodeURIComponent function`  
クエリ文字列のパーセントエンコーディングされた文字を decode する関数です。デフォルトでは、`querystring.unescape()` です。  
`maxKeys number`  
解析するキーの最大数。デフォルトでは、`1000` です。キーカウントの制限を解除するには、`0` の値を使用します。
デフォルトでは、クエリ文字列のパーセントエンコーディングされた文字は、UTF-8 エンコーディングを使用していると見なされます。無効な UTF-8 シーケンスは、`U+FFFD` 置換文字に置き換えられます。  
たとえば、次のクエリ文字列の場合:  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()`の戻り値は次のとおりです。  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` は のエイリアスです。`querystring.parse()`

`querystring.stringify(object[, separator[, equal[, options]]])`  
`object` をシリアル化し、クエリ文字列を返します。  
`separator` パラメータは、クエリ文字列のキーと値のペアを区切る substring です。デフォルトでは、`&` です。  
`equal` パラメータは、クエリ文字列のキーと値を区切る substring です。デフォルトでは、`=` です。  
`options` パラメータは、以下のキーを持つオブジェクトです。    
`encodeURIComponent function`  
URL-unsafe 文字をクエリ文字列のパーセントエンコーディングに変換するために使用される関数です。デフォルトでは、`querystring.escape()` です。
デフォルトでは、クエリ文字列でパーセントエンコーディングが必要な文字は UTF-8 としてエンコードされます。別のエンコーディングを使用するには、`encodeURIComponent` オプションを指定します。  
以下のコードでの例:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
戻り値:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` は のエイリアスです。`querystring.stringify()`

`querystring.unescape(string)`  
指定された `string` 内の URL パーセントエンコーディングされた文字をデコードし、エスケープしていないクエリ文字列を返します。このメソッドは `querystring.parse()`で使用するため、直接使用しないでください。

## 制限された機能
<a name="writing-functions-javascript-features-restricted-features"></a>

次の JavaScript 言語機能は、セキュリティ上の問題により、サポートされていないか、制限されています。

**動的コード評価**  
動的コード評価はサポートされていません。`eval()`、`Function` 両方のコンストラクタが試行された場合、エラーをスローします。たとえば、`const sum = new Function('a', 'b', 'return a + b')` はエラーをスローします。

**タイマー **  
`setTimeout()`、`setImmediate()`、`clearTimeout()` 関数はサポートされていません。関数実行中に defer または yield する規定はありません。関数は同期的に実行しないと完了できません。

**日付とタイムスタンプ**  
セキュリティ上の理由から、高解像度タイマーにはアクセスできません。現在の時刻を照会するすべての `Date` メソッドは、単一の関数実行の存続期間中は常に同じ値を返します。返されるタイムスタンプは、関数の実行を開始した時刻です。したがって、関数内で経過時間を測定することはできません。

**ファイルシステムへのアクセス**  
ファイルシステムにはアクセスできません。たとえば、Node.js にあるようなファイルシステムアクセス用の `fs` モジュールはありません。

**プロセスへのアクセス**  
プロセスにはアクセスできません。例えば、Node.js にあるような、情報アクセスを処理するための `process` グローバルオブジェクトはありません。

**環境変数**  
環境変数にはアクセスできません。  
この代わりに、CloudFront KeyValueStore を使用して、CloudFront Functions のための key-value ペアの一元化されたデータストアを作成できます。CloudFront KeyValueStore を使用すると、コード変更をデプロイする必要なく、設定データを動的に更新できます。CloudFront KeyValueStore を使用するには、[JavaScript ランタイム 2.0](functions-javascript-runtime-20.md) を使用する必要があります。詳細については、「[Amazon CloudFront KeyValueStore](kvs-with-functions.md)」を参照してください。

**ネットワークアクセス**  
ネットワークコールはサポートされていません。たとえば、XHR、HTTP (S)、ソケットはサポートされていません。

# CloudFront Functions の JavaScript ランタイム 2.0 の機能
<a name="functions-javascript-runtime-20"></a>

CloudFront Functions の JavaScript ランタイム環境は [ ECMAScript (ES) バージョン 5.1](https://262.ecma-international.org/5.1/) に準拠しており、ES バージョン 6～12 の一部の機能をサポートしています。また、ES 仕様に含まれない非標準メソッドも提供しています。次のトピックでは、このランタイムでサポートされるすべての機能を一覧表示します。

**Topics**
+ [主要機能](#writing-functions-javascript-features-core-20)
+ [プリミティブオブジェクト](#writing-functions-javascript-features-primitive-objects-20)
+ [ビルトインオブジェクト](#writing-functions-javascript-features-builtin-objects-20)
+ [エラーのタイプ](#writing-functions-javascript-features-error-types-20)
+ [Globals](#writing-functions-javascript-features-globals-20)
+ [ビルトインモジュール](#writing-functions-javascript-features-builtin-modules-20)
+ [制限された機能](#writing-functions-javascript-features-restricted-features-20)

## 主要機能
<a name="writing-functions-javascript-features-core-20"></a>

ES の次の主要機能がサポートされています。

**Types]**  
すべての ES 5.1 タイプでサポートされています。これには、ブール値、数値、文字列、オブジェクト、配列、関数、正規表現が含まれます。

**演算子**  
すべての ES 5.1 演算子でサポートされています。  
ES 7 指数演算子 (`**`) がサポートされています。

**ステートメント**  
次の ES 5.1 ステートメントがサポートされています。  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `label`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
次の ES 6 ステートメントがサポートされています。  
+ `const`
+ `let`
次の ES 8 ステートメントがサポートされています。  
+ `async`
+ `await`
`async`、`await`、`const`、`let` は JavaScript ランタイム 2.0 でサポートされています。  
`await` は `async` 関数内でのみ使用できます。`async` 引数とクロージャはサポートされていません。

**リテラル**  
ES 6 テンプレートリテラル (複数行の文字列、式の補間、および入れ子テンプレート) がサポートされています。

**関数**  
すべての ES 5.1 機能がサポートされています。  
ES 6 のアロー関数、ES 6 のレストパラメータ (残余因数) 構文がサポートされています。

**Unicode**  
ソーステキストおよび文字列リテラルには、Unicode でエンコードされた文字を含めることができます。6 文字の Unicode エスケープシーケンス (コードポイント、例: `\uXXXX`) もサポートされています。

**Strict モード**  
関数は Strict モードで動作するため、関数コードに `use strict` ステートメントを追加する必要はありません。これは変更できません。

## プリミティブオブジェクト
<a name="writing-functions-javascript-features-primitive-objects-20"></a>

以下の ES プリミティブオブジェクトがサポートされています。

**オブジェクト**  
オブジェクトについて以下の ES 5.1 メソッドがサポートされています。  
+ `Object.create()` (プロパティリストなし)
+ `Object.defineProperties()`
+ `Object.defineProperty()`
+ `Object.freeze()`
+ `Object.getOwnPropertyDescriptor()`
+ `Object.getOwnPropertyDescriptors()`
+ `Object.getOwnPropertyNames()`
+ `Object.getPrototypeOf()`
+ `Object.isExtensible()`
+ `Object.isFrozen()`
+ `Object.isSealed()`
+ `Object.keys()`
+ `Object.preventExtensions()`
+ `Object.seal()`
オブジェクトについて以下の ES 6 メソッドがサポートされています。  
+ `Object.assign()`
オブジェクトについて以下の ES 8 メソッドがサポートされています。  
+ `Object.entries()`
+ `Object.values()`
オブジェクトについて以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `Object.prototype.hasOwnProperty()`
+ `Object.prototype.isPrototypeOf()`
+ `Object.prototype.propertyIsEnumerable()`
+ `Object.prototype.toString()`
+ `Object.prototype.valueOf()`
オブジェクトについて以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `Object.prototype.is()`
+ `Object.prototype.setPrototypeOf()`

**String**  
文字列について以下の ES 5.1 メソッドがサポートされています。  
+ `String.fromCharCode()`
文字列について以下の ES 6 メソッドがサポートされています。  
+ `String.fromCodePoint()`
文字列について以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `String.prototype.charAt()`
+ `String.prototype.concat()`
+ `String.prototype.indexOf()`
+ `String.prototype.lastIndexOf()`
+ `String.prototype.match()`
+ `String.prototype.replace()`
+ `String.prototype.search()`
+ `String.prototype.slice()`
+ `String.prototype.split()`
+ `String.prototype.substr()`
+ `String.prototype.substring()`
+ `String.prototype.toLowerCase()`
+ `String.prototype.trim()`
+ `String.prototype.toUpperCase()`
文字列について以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `String.prototype.codePointAt()`
+ `String.prototype.endsWith()`
+ `String.prototype.includes()`
+ `String.prototype.repeat()`
+ `String.prototype.startsWith()`
文字列について以下の ES 8 プロトタイプメソッドがサポートされています。  
+ `String.prototype.padStart()`
+ `String.prototype.padEnd()`
文字列について以下の ES 9 プロトタイプメソッドがサポートされています。  
+ `String.prototype.trimStart()`
+ `String.prototype.trimEnd()`
文字列について以下の ES 12 プロトタイプメソッドがサポートされています。  
+ `String.prototype.replaceAll()`
**注記**  
`String.prototype.replaceAll()` は JavaScript ランタイム 2.0 で新しく追加されました。

**Number**  
すべての ES 5 番号がサポートされています。  
番号について以下の ES 6 プロパティがサポートされています。  
+ `Number.EPSILON`
+ `Number.MAX_SAFE_INTEGER`
+ `Number.MIN_SAFE_INTEGER`
+ `Number.MAX_VALUE`
+ `Number.MIN_VALUE`
+ `Number.NaN`
+ `Number.NEGATIVE_INFINITY`
+ `Number.POSITIVE_INFINITY`
番号について以下の ES 6 メソッドがサポートされています。  
+ `Number.isFinite()`
+ `Number.isInteger()`
+ `Number.isNaN()`
+ `Number.isSafeInteger()`
+ `Number.parseInt()`
+ `Number.parseFloat()`
番号について以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `Number.prototype.toExponential()`
+ `Number.prototype.toFixed()`
+ `Number.prototype.toPrecision()`
ES 12 数字区切り文字がサポートされています。  
ES 12 数字区切り文字は JavaScript ランタイム 2.0 で新しく追加されました。

## ビルトインオブジェクト
<a name="writing-functions-javascript-features-builtin-objects-20"></a>

ES の以下のビルトインオブジェクトがサポートされています。

**Math**  
ES 5.1 のすべての Math メソッドがサポートされています。  
CloudFront Functions runtime 環境では、`Math.random()` 実装に、関数が実行されたときのタイムスタンプがシードされた OpenBSD `arc4random` を使用します。
以下の ES 6 数学的プロパティがサポートされています。  
+ `Math.E`
+ `Math.LN10`
+ `Math.LN2`
+ `Math.LOG10E`
+ `Math.LOG2E`
+ `Math.PI`
+ `Math.SQRT1_2`
+ `Math.SQRT2`
以下の ES 6 Math メソッドがサポートされています。  
+ `Math.abs()`
+ `Math.acos()`
+ `Math.acosh()`
+ `Math.asin()`
+ `Math.asinh()`
+ `Math.atan()`
+ `Math.atan2()`
+ `Math.atanh()`
+ `Math.cbrt()`
+ `Math.ceil()`
+ `Math.clz32()`
+ `Math.cos()`
+ `Math.cosh()`
+ `Math.exp()`
+ `Math.expm1()`
+ `Math.floor()`
+ `Math.fround()`
+ `Math.hypot()`
+ `Math.imul()`
+ `Math.log()`
+ `Math.log1p()`
+ `Math.log2()`
+ `Math.log10()`
+ `Math.max()`
+ `Math.min()`
+ `Math.pow()`
+ `Math.random()`
+ `Math.round()`
+ `Math.sign()`
+ `Math.sinh()`
+ `Math.sin()`
+ `Math.sqrt()`
+ `Math.tan()`
+ `Math.tanh()`
+ `Math.trunc()`

**日付**  
すべての ES 5.1 の `Date` 機能がサポートされています。  
セキュリティ上の理由から、`Date` は、単一の関数実行の有効期間中、常に同じ値 (関数の開始時間) を返します。詳細については、「[制限された機能](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features)」を参照してください。

**関数**  
以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `Function.prototype.apply()`
+ `Function.prototype.bind()`
+ `Function.prototype.call()`
関数コンストラクタはサポートされていません。

**正規表現**  
すべての ES 5.1 の正規表現機能がサポートされています。正規表現言語は Perl 互換です。  
以下の ES 5.1 プロトタイプアクセサプロパティがサポートされています。  
+ `RegExp.prototype.global`
+ `RegExp.prototype.ignoreCase`
+ `RegExp.protoype.multiline`
+ `RegExp.protoype.source`
+ `RegExp.prototype.sticky`
+ `RegExp.prototype.flags`
**注記**  
`RegExp.prototype.sticky` および `RegExp.prototype.flags` は JavaScript ランタイム 2.0 で新しく追加されました。
以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `RegExp.prototype.exec()`
+ `RegExp.prototype.test()`
+ `RegExp.prototype.toString()`
+ `RegExp.prototype[@@replace]()`
+ `RegExp.prototype[@@split]()`
**注記**  
`RegExp.prototype[@@split]()` は JavaScript ランタイム 2.0 で新しく追加されました。
以下の ES 5.1 インスタンスプロパティがサポートされています。  
+ `lastIndex`
ES 9 の名前付きキャプチャグループがサポートされています。

**JSON**  
以下の ES 5.1 メソッドがサポートされています。  
+ `JSON.parse()`
+ `JSON.stringify()`

**配列**  
配列について以下の ES 5.1 メソッドがサポートされています。  
+ `Array.isArray()`
配列について以下の ES 6 メソッドがサポートされています。  
+ `Array.of()`
以下の ES 5.1 プロトタイプメソッドがサポートされています。  
+ `Array.prototype.concat()`
+ `Array.prototype.every()`
+ `Array.prototype.filter()`
+ `Array.prototype.forEach()`
+ `Array.prototype.indexOf()`
+ `Array.prototype.join()`
+ `Array.prototype.lastIndexOf()`
+ `Array.prototype.map()`
+ `Array.prototype.pop()`
+ `Array.prototype.push()`
+ `Array.prototype.reduce()`
+ `Array.prototype.reduceRight()`
+ `Array.prototype.reverse()`
+ `Array.prototype.shift()`
+ `Array.prototype.slice()`
+ `Array.prototype.some()`
+ `Array.prototype.sort()`
+ `Array.prototype.splice()`
+ `Array.prototype.unshift()`
以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `Array.prototype.copyWithin()`
+ `Array.prototype.fill()`
+ `Array.prototype.find()`
+ `Array.prototype.findIndex()`
以下の ES 7 プロトタイプメソッドがサポートされています。  
+ `Array.prototype.includes()`

**型付き配列**  
以下の ES 6 型付き配列コンストラクターがサポートされています。  
+ `Float32Array`
+ `Float64Array`
+ `Int8Array`
+ `Int16Array`
+ `Int32Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Uint16Array`
+ `Uint32Array`
以下の ES 6 メソッドがサポートされています。  
+ `TypedArray.from()`
+ `TypedArray.of()`
**注記**  
`TypedArray.from()` および `TypedArray.of()` は JavaScript ランタイム 2.0 で新しく追加されました。
以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `TypedArray.prototype.copyWithin()`
+ `TypedArray.prototype.every()`
+ `TypedArray.prototype.fill()`
+ `TypedArray.prototype.filter()`
+ `TypedArray.prototype.find()`
+ `TypedArray.prototype.findIndex()`
+ `TypedArray.prototype.forEach()`
+ `TypedArray.prototype.includes()`
+ `TypedArray.prototype.indexOf()`
+ `TypedArray.prototype.join()`
+ `TypedArray.prototype.lastIndexOf()`
+ `TypedArray.prototype.map()`
+ `TypedArray.prototype.reduce()`
+ `TypedArray.prototype.reduceRight()`
+ `TypedArray.prototype.reverse()`
+ `TypedArray.prototype.some()`
+ `TypedArray.prototype.set()`
+ `TypedArray.prototype.slice()`
+ `TypedArray.prototype.sort()`
+ `TypedArray.prototype.subarray()`
+ `TypedArray.prototype.toString()`
**注記**  
`TypedArray.prototype.every()`、`TypedArray.prototype.fill()`、`TypedArray.prototype.filter()`、`TypedArray.prototype.find()`、`TypedArray.prototype.findIndex()`、`TypedArray.prototype.forEach()`、`TypedArray.prototype.includes()`、`TypedArray.prototype.indexOf()`、`TypedArray.prototype.join()`、`TypedArray.prototype.lastIndexOf()`、`TypedArray.prototype.map()`、`TypedArray.prototype.reduce()`、`TypedArray.prototype.reduceRight()`、`TypedArray.prototype.reverse()`、および `TypedArray.prototype.some()` は JavaScript ランタイム 2.0 で新しく追加されました。

**ArrayBuffer**  
ArrayBuffer について以下の ES 6 メソッドがサポートされています。  
+ `isView()`
ArrayBuffer について以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `ArrayBuffer.prototype.slice()`

**promise**  
Promise について以下の ES 6 メソッドがサポートされています。  
+ `Promise.all()`
+ `Promise.allSettled()`
+ `Promise.any()`
+ `Promise.reject()`
+ `Promise.resolve()`
+ `Promise.race()`
**注記**  
`Promise.all()`、`Promise.allSettled()`、`Promise.any()`、`Promise.race()` は JavaScript ランタイム 2.0 で新しく追加されました。
Promise について以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `Promise.prototype.catch()`
+ `Promise.prototype.finally()`
+ `Promise.prototype.then()`

**DataView**  
以下の ES 6 プロトタイプメソッドがサポートされています。  
+ `DataView.prototype.getFloat32()`
+ `DataView.prototype.getFloat64()`
+ `DataView.prototype.getInt16()`
+ `DataView.prototype.getInt32()`
+ `DataView.prototype.getInt8()`
+ `DataView.prototype.getUint16()`
+ `DataView.prototype.getUint32()`
+ `DataView.prototype.getUint8()`
+ `DataView.prototype.setFloat32()`
+ `DataView.prototype.setFloat64()`
+ `DataView.prototype.setInt16()`
+ `DataView.prototype.setInt32()`
+ `DataView.prototype.setInt8()`
+ `DataView.prototype.setUint16()`
+ `DataView.prototype.setUint32()`
+ `DataView.prototype.setUint8()`
**注記**  
Dataview ES 6 のプロトタイプメソッドはすべて JavaScript ランタイム 2.0 で新しく追加されました。

**記号**  
以下の ES 6 メソッドがサポートされています。  
+ `Symbol.for()`
+ `Symbol.keyfor()`
**注記**  
Symbol ES 6 メソッドはすべて JavaScript ランタイム 2.0 で新しく追加されました。

**テキストデコーダー**  
以下のプロトタイプメソッドがサポートされています。  
+ `TextDecoder.prototype.decode()`
以下のプロトタイプアクセサプロパティがサポートされています。  
+ `TextDecoder.prototype.encoding`
+ `TextDecoder.prototype.fatal`
+ `TextDecoder.prototype.ignoreBOM`

**テキストエンコーダー**  
以下のプロトタイプメソッドがサポートされています。  
+ `TextEncoder.prototype.encode()`
+ `TextEncoder.prototype.encodeInto()`

## エラーのタイプ
<a name="writing-functions-javascript-features-error-types-20"></a>

以下のエラーオブジェクトがサポートされています。
+ `Error`
+ `EvalError`
+ `InternalError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## Globals
<a name="writing-functions-javascript-features-globals-20"></a>

`globalThis` オブジェクトはサポートされています。

以下の ES 5.1 グローバル関数がサポートされています。
+ `decodeURI()`
+ `decodeURIComponent()`
+ `encodeURI()`
+ `encodeURIComponent()`
+ `isFinite()`
+ `isNaN()`
+ `parseFloat()`
+ `parseInt()`

以下の ES 6 グローバル関数がサポートされています。
+ `atob()`
+ `btoa()`
**注記**  
`atob()` および `btoa()` は JavaScript ランタイム 2.0 で新しく追加されました。

以下のグローバル定数がサポートされています。
+ `NaN`
+ `Infinity`
+ `undefined`
+ `arguments`

## ビルトインモジュール
<a name="writing-functions-javascript-features-builtin-modules-20"></a>

以下のビルトインモジュールがサポートされています。

**Topics**
+ [バッファ](#writing-functions-javascript-features-builtin-modules-buffer-20)
+ [クエリ文字列](#writing-functions-javascript-features-builtin-modules-query-string-20)
+ [Crypto](#writing-functions-javascript-features-builtin-modules-crypto-20)

### バッファ
<a name="writing-functions-javascript-features-builtin-modules-buffer-20"></a>

このモジュールは、以下のメソッドを提供します。
+ `Buffer.alloc(size[, fill[, encoding]])`

  `Buffer` を割り当てます。
  + `size`: バッファサイズ。整数を入力します。
  + `fill`: オプション。文字列、`Buffer`、Uint8Array または整数を入力します。デフォルトは `0` です。
  + `encoding`: オプション。`fill` が文字列である場合は、`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.allocUnsafe(size)`

  初期化されていない `Buffer` を割り当てます。
  + `size`: 整数を入力します。
+ `Buffer.byteLength(value[, encoding])`

  値の長さをバイト単位で返します。
  + `value`: 文字列、`Buffer`、TypedArray、Dataview、または Arraybuffer。
  + `encoding`: オプション。`value` が文字列である場合は、`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.compare(buffer1, buffer2)`

  2 つの `Buffer` を比較すると、配列をソートしやすくなります。両者が同じ場合は `0`、`buffer1` が先に来る場合は `-1`、`buffer2` が先に来る場合は `1` を返します。
  + `buffer1`: `Buffer` を入力します。
  + `buffer2`: 別の `Buffer` 値を入力します。
+ `Buffer.concat(list[, totalLength])`

  複数の `Buffer` を連結します。ない場合は `0` を返します。`totalLength` までの値を返します。
  + `list`: `Buffer` のリストを入力します。これは `totalLength` に切り捨てられることに注意してください。
  + `totalLength`: オプション。符号なし整数を入力します。空欄の場合はリスト内の `Buffer` インスタンス総数を使用します。
+ `Buffer.from(array)`

  配列から `Buffer` を作成します。
  + `array`: `0` から `255` までのバイト配列を入力します。
+ `Buffer.from(arrayBuffer, byteOffset[, length]))`

  オフセット `byteOffset` から始めて長さが `length` のビューを `arrayBuffer` から作成します。
  + `arrayBuffer`: `Buffer` 配列を入力します。
  + `byteOffset`: 整数を入力します。
  + `length`: オプション。整数を入力します。
+ `Buffer.from(buffer)`

  `Buffer` のコピーを作成します。
  + `buffer`: `Buffer` を入力します。
+ `Buffer.from(object[, offsetOrEncoding[, length]])`

  オブジェクトから `Buffer` を作成します。`valueOf()` がオブジェクトと等しくない場合は `Buffer.from(object.valueOf(), offsetOrEncoding, length)` を返します。
  + `object`: オブジェクトを入力します。
  + `offsetOrEncoding`: オプション。整数またはエンコーディング文字列を入力します。
  + `length`: オプション。整数を入力します。
+ `Buffer.from(string[, encoding])`

  文字列から `Buffer` を作成します。
  + `string`: 文字列を入力します。
  + `encoding`: オプション。`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.isBuffer(object)`

  `object` がバッファかどうかをチェックします。`true` または `false` を返します。
  + `object`: オブジェクトを入力します。
+ `Buffer.isEncoding(encoding)`

  `encoding` がサポートされているかをチェックします。`true` または `false` を返します。
  + `encoding`: オプション。`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。

このモジュールは、以下のバッファプロトタイプメソッドを提供します。
+ `Buffer.prototype.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])`

  ターゲットと `Buffer` を比較します。両者が同じ場合は `0`、`buffer` が先に来る場合は `1`、`target` が先に来る場合は `-1` を返します。
  + `target`: `Buffer` を入力します。
  + `targetStart`: オプション。整数を入力します。デフォルトは 0 です。
  + `targetEnd`: オプション。整数を入力します。デフォルトは `target` の長さです。
  + `sourceStart`: オプション。整数を入力します。デフォルトは 0 です。
  + `sourceEnd`: オプション。整数を入力します。デフォルトは `Buffer` の長さです。
+ `Buffer.prototype.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`

  バッファを `target` にコピーします。
  + `target`: `Buffer` または `Uint8Array` を入力します。
  + `targetStart`: オプション。整数を入力します。デフォルトは 0 です。
  + `sourceStart`: オプション。整数を入力します。デフォルトは 0 です。
  + `sourceEnd`: オプション。整数を入力します。デフォルトは `Buffer` の長さです。
+ `Buffer.prototype.equals(otherBuffer)`

  `Buffer` と `otherBuffer` を比較します。`true` または `false` を返します。
  + `otherBuffer`: 文字列を入力します。
+ `Buffer.prototype.fill(value[, offset[, end][, encoding])`

  `value` に `Buffer` を入力します。
  + `value`: 文字列、`Buffer`、または整数を入力します。
  + `offset`: オプション。整数を入力します。
  + `end`: オプション。整数を入力します。
  + `encoding`: オプション。`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.prototype.includes(value[, byteOffset][, encoding])`

  `value` で `Buffer` を検索します。`true` または `false` を返します。
  + `value`: 文字列、`Buffer`、`Uint8Array`、または整数を入力します。
  + `byteOffset`: オプション。整数を入力します。
  + `encoding`: オプション。`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.prototype.indexOf(value[, byteOffset][, encoding])`

  `Buffer` で最初の `value` を検索します。見つかった場合は `index` を返し、見つからなかった場合は `-1` を返します。
  + `value`: 文字列、`Buffer`、Unit8Array、または 0 から 255 までの整数を入力します。
  + `byteOffset`: オプション。整数を入力します。
  + `encoding`: オプション。`value` が文字列の場合、`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.prototype.lastIndexOf(value[, byteOffset][, encoding])`

  `Buffer` で最後の `value` を検索します。見つかった場合は `index` を返し、見つからなかった場合は `-1` を返します。
  + `value`: 文字列、`Buffer`、Unit8Array、または 0 から 255 までの整数を入力します。
  + `byteOffset`: オプション。整数を入力します。
  + `encoding`: オプション。`value` が文字列の場合、`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.prototype.readInt8(offset)`

  `Buffer` から `offset` で `Int8` を読み込みます。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readIntBE(offset, byteLength)`

  `Buffer` から `offset` で `Int` をビッグエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
  + `byteLength`: オプション。`1` から `6` までの整数を入力します。
+ `Buffer.prototype.readInt16BE(offset)`

  `Buffer` から `offset` で `Int16` をビッグエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readInt32BE(offset)`

  `Buffer` から `offset` で `Int32` をビッグエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readIntLE(offset, byteLength)`

  `Buffer` から `offset` で `Int` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.readInt16LE(offset)`

  `Buffer` から `offset` で `Int16` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readInt32LE(offset)`

  `Buffer` から `offset` で `Int32` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readUInt8(offset)`

  `Buffer` から `offset` で `UInt8` を読み込みます。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readUIntBE(offset, byteLength)`

  `Buffer` から `offset` で `UInt` をビッグエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.readUInt16BE(offset)`

  `Buffer` から `offset` で `UInt16` をビッグエンディアンとして読み取ります。
+ 
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readUInt32BE(offset)`

  `Buffer` から `offset` で `UInt32` をビッグエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readUIntLE(offset, byteLength)`

  `Buffer` から `offset` で `UInt` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.readUInt16LE(offset)`

  `Buffer` から `offset` で `UInt16` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readUInt32LE(offset)`

  `Buffer` から `offset` で `UInt32` をリトルエンディアンとして読み取ります。
  + `offset`: 整数を入力します。
+ `Buffer.prototype.readDoubleBE([offset])`

  `Buffer` から `offset` で 64 ビットダブルをビッグエンディアンとして読み込みます。
  + `offset`: オプション。整数を入力します。
+ `Buffer.prototype.readDoubleLE([offset])`

  `Buffer` から `offset` で 64 リトルダブルをビッグエンディアンとして読み込みます。
  + `offset`: オプション。整数を入力します。
+ `Buffer.prototype.readFloatBE([offset])`

  `Buffer` から `offset` で 32 ビットフロートをビッグエンディアンとして読み込みます。
  + `offset`: オプション。整数を入力します。
+ `Buffer.prototype.readFloatLE([offset])`

  `Buffer` から `offset` で 32 ビットフロートをリトルエンディアンとして読み込みます。
  + `offset`: オプション。整数を入力します。
+ `Buffer.prototype.subarray([start[, end]])`

  オフセットし、新しい `start` および `end` で切り取った `Buffer` のコピーを返します。
  + `start`: オプション。整数を入力します。デフォルトは 0 です。
  + `end`: オプション。整数を入力します。デフォルトはバッファの長さです。
+ `Buffer.prototype.swap16()`

  `Buffer` 配列のバイト順を入れ替え、16 ビットの数値の配列として扱います。`Buffer` の長さは 2 で割り切れる必要があります。そうしないと、エラーになります。
+ `Buffer.prototype.swap32()`

  `Buffer` 配列のバイト順を入れ替え、32 ビットの数値の配列として扱います。`Buffer` の長さは 4 で割り切れる必要があります。そうしないと、エラーになります。
+ `Buffer.prototype.swap64()`

  `Buffer` 配列のバイト順を入れ替え、64 ビットの数値の配列として扱います。`Buffer` の長さは 8 で割り切れる必要があります。そうしないと、エラーになります。
+ `Buffer.prototype.toJSON()`

  JSON として `Buffer` を返します。
+ `Buffer.prototype.toString([encoding[, start[, end]]])`

  `start` から `end` まで `Buffer` をエンコードされた文字列に変換します。
  + `encoding`: オプション。`utf8`、`hex`、`base64`、`base64url` のいずれかを入力します。デフォルトは `utf8` です。
  + `start`: オプション。整数を入力します。デフォルトは 0 です。
  + `end`: オプション。整数を入力します。デフォルトはバッファの長さです。
+ `Buffer.prototype.write(string[, offset[, length]][, encoding])`

  スペースがある場合はエンコードされた `string` を `Buffer` に書き込み、十分なスペースがない場合は切り捨てられた `string` になります。
  + `string`: 文字列を入力します。
  + `offset`: オプション。整数を入力します。デフォルトは 0 です。
  + `length`: オプション。整数を入力します。デフォルトは文字列の長さです。
  + `encoding`: オプション。オプションで、`utf8`、`hex`、`base64`、または `base64url` のいずれかを入力します。デフォルトは `utf8` です。
+ `Buffer.prototype.writeInt8(value, offset, byteLength)`

  `offset` で `byteLength` の `Int8` `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeIntBE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeInt16BE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeInt32BE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeIntLE(offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeInt16LE(offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeInt32LE(offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `offset`: 整数を入力します。
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUInt8(value, offset, byteLength)`

  `offset` で `byteLength` の `UInt8` `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUIntBE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUInt16BE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUInt32BE(value, offset, byteLength)`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUIntLE(value, offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUInt16LE(value, offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeUInt32LE(value, offset, byteLength)`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  + `offset`: 整数を入力します
  + `byteLength`: `1` から `6` までの整数を入力します。
+ `Buffer.prototype.writeDoubleBE(value, [offset])`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  +  `offset`: オプション。整数を入力します。デフォルトは 0 です。
+ `Buffer.prototype.writeDoubleLE(value, [offset])`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  +  `offset`: オプション。整数を入力します。デフォルトは 0 です。
+ `Buffer.prototype.writeFloatBE(value, [offset])`

  ビッグエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  +  `offset`: オプション。整数を入力します。デフォルトは 0 です。
+ `Buffer.prototype.writeFloatLE(value, [offset])`

  リトルエンディアンを使用して `offset` の `value` を `Buffer` に書き込みます。
  + `value`: 整数を入力します。
  +  `offset`: オプション。整数を入力します。デフォルトは 0 です。

以下のインスタンスメソッドがサポートされています。
+ `buffer[index]`

  `Buffer` `index` でオクテット (バイト) を取得および設定します。
  + `0` から `255` までの数値を取得します。または、`0` から `255` までの数値を設定します。

以下のインスタンスプロパティがサポートされています。
+ `buffer`

  バッファの `ArrayBuffer` オブジェクトを取得します。
+ `byteOffset`

  バッファの `Arraybuffer` オブジェクトの `byteOffset` を取得します。
+ `length`

  バッファのバイト数を取得します。

**注記**  
バッファモジュールメソッドはすべて JavaScript ランタイム 2.0 で新しく追加されました。

### クエリ文字列
<a name="writing-functions-javascript-features-builtin-modules-query-string-20"></a>

**注記**  
[CloudFront Functions イベントオブジェクト](functions-event-structure.md)は、URL クエリ文字列を自動的に解析します。つまり、ほとんどの場合、このモジュールを使用する必要はありません。

クエリ文字列モジュール (`querystring`) は、URL クエリ文字列を解析および書式設定するためのメソッドを提供します。`require('querystring')` を使用してモジュールをロードできます。このモジュールは、以下のメソッドを提供します。

`querystring.escape(string)`  
URL は `string` をエンコードし、エスケープしたクエリ文字列を返します。このメソッドは `querystring.stringify()` で使用するため、直接使用しないでください。

`querystring.parse(string[, separator[, equal[, options]]])`  
クエリ文字列 (`string`) を解析し、オブジェクトを返します。  
`separator` パラメータは、クエリ文字列のキーと値のペアを区切る substring です。デフォルトでは、`&` です。  
`equal` パラメータは、クエリ文字列のキーと値を区切る substring です。デフォルトでは、`=` です。  
`options` パラメータは、以下のキーを持つオブジェクトです。    
`decodeURIComponent function`  
クエリ文字列のパーセントエンコーディングされた文字を decode する関数です。デフォルトでは、`querystring.unescape()` です。  
`maxKeys number`  
解析するキーの最大数。デフォルトでは、`1000` です。キーカウントの制限を解除するには、`0` の値を使用します。
デフォルトでは、クエリ文字列のパーセントエンコーディングされた文字は、UTF-8 エンコーディングを使用していると見なされます。無効な UTF-8 シーケンスは、`U+FFFD` 置換文字に置き換えられます。  
たとえば、次のクエリ文字列の場合:  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()`の戻り値は次のとおりです。  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` は のエイリアスです。`querystring.parse()`

`querystring.stringify(object[, separator[, equal[, options]]])`  
`object` をシリアル化し、クエリ文字列を返します。  
`separator` パラメータは、クエリ文字列のキーと値のペアを区切る substring です。デフォルトでは、`&` です。  
`equal` パラメータは、クエリ文字列のキーと値を区切る substring です。デフォルトでは、`=` です。  
`options` パラメータは、以下のキーを持つオブジェクトです。    
`encodeURIComponent function`  
URL-unsafe 文字をクエリ文字列のパーセントエンコーディングに変換するために使用される関数です。デフォルトでは、`querystring.escape()` です。
デフォルトでは、クエリ文字列でパーセントエンコーディングが必要な文字は UTF-8 としてエンコードされます。別のエンコーディングを使用するには、`encodeURIComponent` オプションを指定します。  
以下のコードでの例:  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
戻り値:  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` は のエイリアスです。`querystring.stringify()`

`querystring.unescape(string)`  
指定された `string` 内の URL パーセントエンコーディングされた文字をデコードし、エスケープしていないクエリ文字列を返します。このメソッドは `querystring.parse()`で使用するため、直接使用しないでください。

### Crypto
<a name="writing-functions-javascript-features-builtin-modules-crypto-20"></a>

暗号モジュール (`crypto`) は、標準のハッシュおよびハッシュベースのメッセージ認証コード (HMAC) ヘルパーを提供します。`require('crypto')` を使用してモジュールをロードできます。

**ハッシュメソッド**

`crypto.createHash(algorithm)`  
ハッシュオブジェクトを作成して返します。このハッシュオブジェクトは、指定されたアルゴリズム (`md5`、`sha1`、`sha256` のいずれか) を使用してハッシュダイジェストの生成に使用できます。

`hash.update(data)`  
指定された `data` を使用してハッシュコンテンツを更新します。

`hash.digest([encoding])`  
`hash.update()` を使用して渡されたすべてのデータのダイジェストを計算します。エンコードは `hex`、`base64`、`base64url` のいずれかを使用します。

**HMAC メソッド**

`crypto.createHmac(algorithm, secret key)`  
指定された `algorithm` と `secret key` を使用する HMAC オブジェクトを作成して返します。アルゴリズムは `md5`、`sha1`、`sha256` のいずれかを使用します。

`hmac.update(data)`  
指定された `data` を使用して HMAC コンテンツを更新します 。

`hmac.digest([encoding])`  
`hmac.update()` を使用して渡されたすべてのデータのダイジェストを計算します。エンコードは `hex`、`base64`、`base64url` のいずれかを使用します。

## 制限された機能
<a name="writing-functions-javascript-features-restricted-features-20"></a>

次の JavaScript 言語機能は、セキュリティ上の問題により、サポートされていないか、制限されています。

**動的コード評価**  
動的コード評価はサポートされていません。`eval()`、`Function` 両方のコンストラクタが試行された場合、エラーをスローします。たとえば、`const sum = new Function('a', 'b', 'return a + b')` はエラーをスローします。

**タイマー **  
`setTimeout()`、`setImmediate()`、`clearTimeout()` 関数はサポートされていません。関数実行中に defer または yield する規定はありません。関数は同期的に実行しないと完了できません。

**日付とタイムスタンプ**  
セキュリティ上の理由から、高解像度タイマーにはアクセスできません。現在の時刻を照会するすべての `Date` メソッドは、単一の関数実行の存続期間中は常に同じ値を返します。返されるタイムスタンプは、関数の実行を開始した時刻です。したがって、関数内で経過時間を測定することはできません。

**ファイルシステムへのアクセス**  
ファイルシステムにはアクセスできません。たとえば、Node.js にあるようなファイルシステムアクセス用の `fs` モジュールはありません。

**プロセスへのアクセス**  
プロセスにはアクセスできません。例えば、Node.js にあるような、情報アクセスを処理するための `process` グローバルオブジェクトはありません。

**環境変数**  
環境変数にはアクセスできません。この代わりに、CloudFront KeyValueStore を使用して、CloudFront Functions のための key-value ペアの一元化されたデータストアを作成できます。CloudFront KeyValueStore を使用すると、コード変更をデプロイする必要なく、設定データを動的に更新できます。詳細については、「[Amazon CloudFront KeyValueStore](kvs-with-functions.md)」を参照してください。

**ネットワークアクセス**  
ネットワークコールはサポートされていません。たとえば、XHR、HTTP (S)、ソケットはサポートされていません。

# キーバリューストアのヘルパーメソッド
<a name="functions-custom-methods"></a>

**注記**  
CloudFront Functions からのキーバリューストアのヘルパーメソッド呼び出しは、AWS CloudTrail データイベントをトリガーしません。これらのイベントは CloudTrail イベント履歴には記録されません。詳細については、「[AWS CloudTrail を使用した Amazon CloudFront API コールのログ記録](logging_using_cloudtrail.md)」を参照してください。

このセクションは、[CloudFront キーバリューストア](kvs-with-functions.md)を使用して作成する関数にキー値を含める場合に適用されます。CloudFront Functions には、キーバリューストアから値を読み取る 3 つのヘルパーメソッドを提供するモジュールがあります。

このモジュールを関数コードで使用するには、関数に[キーバリューストアを関連付ける](kvs-with-functions-associate.md)必要があります。

次に、関数コードの最初の行に、以下のステートメントを含めます。

```
import cf from 'cloudfront';
const kvsHandle = cf.kvs();
```



## `get()` 方法
<a name="functions-custom-methods-get"></a>

このメソッドを使用して、指定したキー名のキー値を返します。

**[リクエスト**]

```
get("key", options);
```
+ `key`: 値をフェッチする必要があるキーの名前
+ `options`: 1 つのオプション `format` があります。これにより、関数はデータを正しく解析します。使用できる値:
  + `string`: (デフォルト) UTF8 エンコード
  + `json` 
  + `bytes`: 未加工のバイナリデータバッファ

**リクエストの例**

```
const value = await kvsHandle.get("myFunctionKey", { format: "string"});
```

**応答**

レスポンスは `promise` であり、`options` を使用してリクエストした形式の値に解決されます。デフォルトでは、値は文字列として返されます。

### エラー処理
<a name="error-handling-exists-method"></a>

リクエストしたキーが、関連するキーバリューストアに存在しない場合、`get()` メソッドはエラーを返します。このユースケースを管理するには、コードに `try` および `catch` ブロックを追加できます。

**警告**  
promise コンビネーター (例: `Promise.all`、`Promise.any`、および promise チェーンメソッド (例: `then` および `catch`) を使用すると、関数のメモリ使用量が高くなる可能性があります。関数が[最大関数メモリ](cloudfront-limits.md#limits-functions)クォータを超えると、実行に失敗します。このエラーを回避するには、`await` 構文を順番に使用するか、ループ内で使用して複数の値をリクエストすることをお勧めします。  
**例**  

```
var value1 = await kvs.get('key1');
var value2 = await kvs.get('key2');
```
現在、promise コンビネーターを使用して複数の値を取得しても、次の例のように、パフォーマンスは向上しません。  

```
var values = await Promise.all([kvs.get('key1'), kvs.get('key2'),]);
```

## `exists()` 方法
<a name="functions-custom-methods-exists"></a>

このメソッドを使用して、キーがキーバリューストアに存在するかどうかを確認します。

**[リクエスト**]

```
exists("key");
```

**リクエストの例**

```
const exist = await kvsHandle.exists("myFunctionkey");
```

**応答**

レスポンスは `promise` であり、ブール値 (`true` または `false`) を返します。この値は、キーがキーバリューストアに存在するかどうかを示します。

## `meta()` 方法
<a name="functions-custom-methods-meta"></a>

このメソッドを使用して、キーバリューストアに関するメタデータを返します。

**[リクエスト**]

```
meta();
```

**リクエストの例**

```
const meta = await kvsHandle.meta();
```

**応答**

レスポンスは `promise` で、以下のプロパティを持つオブジェクトに解決されます。
+ `creationDateTime`: キーバリューストアが作成された ISO 8601 形式の日付と時刻。
+ `lastUpdatedDateTime`: キーバリューストアがソースから最後に同期された ISO 8601 形式の日付と時刻。値にはエッジへの伝達時間は含まれていません。
+ `keyCount`: ソースからの最後の同期後の KVS 内のキーの合計数。

**レスポンスの例**

```
{keyCount:3,creationDateTime:2023-11-30T23:07:55.765Z,lastUpdatedDateTime:2023-12-15T03:57:52.411Z}
```

# オリジン変更のヘルパーメソッド
<a name="helper-functions-origin-modification"></a>

このセクションは、CloudFront Functions コード内のリクエストで使用されているオリジンを動的に更新または変更する場合に適用されます。オリジンは、*ビューワーリクエスト* CloudFront Functions でのみ更新できます。CloudFront Functions には、オリジンを動的に更新または変更するためのヘルパーメソッドを提供するモジュールがあります。

このモジュールを使用するには、JavaScript ランタイム 2.0 を使用して CloudFront 関数を作成し、関数コードの最初の行に次のステートメントを含めます。

```
import cf from 'cloudfront';
```

詳細については、「[CloudFront Functions の JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md)」を参照してください。

**注記**  
テスト API およびテストコンソールページでは、オリジンの変更が発生したかどうかをテストしません。ただし、テストにより、関数コードがエラーなしで実行されることが保証されます。

## CloudFront Functions と Lambda@Edge のどちらかを選択する
<a name="origin-modification-considerations"></a>

CloudFront Functions または Lambda@Edge のどちらかを使用してオリジンを更新できます。

CloudFront Functions を使用してオリジンを更新する場合は、*ビューワーリクエスト*イベントトリガーを使用します。つまり、この関数を使用するたびに、このロジックがすべてのリクエストで実行されます。Lambda@Edge を使用する場合、オリジン更新機能は*オリジンリクエスト*イベントトリガーに存在します。つまり、このロジックはキャッシュミス時にのみ実行されます。

どちらを選択するかは、ワークロードと、ディストリビューションでの CloudFront Functions と Lambda@Edge の既存の使用状況に大きく依存します。以下の考慮事項は、CloudFront Functions と Lambda@Edge のどちらを使用してオリジンを更新するかを決定するのに役立ちます。

CloudFront Functions は、以下の場合に最も役立ちます。
+ リクエストが動的である (つまりキャッシュできない) ため、常にオリジンに送信される場合。CloudFront Functions は、パフォーマンスを向上させ、全体的なコストを削減します。
+ すべてのリクエストで動作する既存のビューワーリクエスト CloudFront 関数が既にある場合。オリジン更新ロジックを既存の関数内に追加できます。

CloudFront Functions を使用してオリジンを更新するには、以下のトピックでヘルパーメソッドを参照してください。

Lambda@Edge は、以下の場合に最も役立ちます。
+ 高度にキャッシュ可能なコンテンツがある場合。CloudFront Functions はすべてのリクエストで実行されるのに対して、Lambda@Edge はキャッシュミス時にのみ実行されるため、コスト効率が向上します。
+ 既存のオリジンリクエスト Lambda@Edge 関数が既にある場合。オリジン更新ロジックを既存の関数内に追加できます。
+ オリジン更新ロジックで、Amazon DynamoDB や Amazon S3 など、サードパーティのデータソースからデータを取得する必要がある場合。

Lambda@Edge の詳細については、「[Lambda@Edge を使用してエッジでカスタマイズする](lambda-at-the-edge.md)」を参照してください。

## updateRequestOrigin() メソッド
<a name="update-request-origin-helper-function"></a>

`updateRequestOrigin()` メソッドは、リクエストのオリジン設定を更新するために使用します。このメソッドを使用して、ディストリビューションで既に定義されているオリジンの既存のオリジンプロパティを更新したり、リクエストの新しいオリジンを定義したりできます。これを行うには、変更するプロパティを指定します。

**重要**  
`updateRequestOrigin()` で指定しない設定は、既存のオリジンの設定から*同じ設定*を継承します。

`updateRequestOrigin()` メソッドで設定するオリジンは、任意の HTTP エンドポイントが可能であり、CloudFront ディストリビューション内の既存のオリジンである必要はありません。

**注意事項**  
オリジングループの一部であるオリジンを更新する場合、オリジングループの*プライマリオリジン*のみが更新されます。セカンダリオリジンは変更されません。フェイルオーバー条件に一致する変更されたオリジンからのレスポンスコードは、セカンダリオリジンへのフェイルオーバーをトリガーします。
オリジンタイプを変更し、OAC が有効になっている場合は、`originAccessControlConfig` のオリジンタイプが新しいオリジンタイプと一致することを確認してください。
`updateRequestOrigin()` メソッドを使用して [VPC オリジン](private-content-vpc-origins.md)を更新することはできません。リクエストは失敗します。

**[リクエスト**]

```
updateRequestOrigin({origin properties})
```

`origin properties` には、以下を含めることができます。

**domainName (オプション）**  
オリジンのドメイン名。これを指定しない場合、割り当てられたオリジンのドメイン名が代わりに使用されます。    
**カスタムオリジンの場合**  
DNS ドメイン名 (`www.example.com` など) を指定します。ドメイン名ではコロン (`:`) を使用できません。IP アドレスも使用できません。ドメイン名の最大長は 253 文字です。  
**S3 オリジンの場合**  
Amazon S3 バケットの DNS ドメイン名 (`amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com` など) を指定します。この名前は最大 128 文字で、すべて小文字であることが必要です。

**hostHeader (オプション、S3 カスタムオリジンでない場合)**  
オリジンにリクエストをするときに使用するホストヘッダー。これを指定しない場合、domainName パラメータの値が使用されます。ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。ホストヘッダーではコロン (`:`) を使用できません。IP アドレスも使用できません。ホストヘッダーは最大 253 文字です。

**originPath (オプション)**  
リクエストがコンテンツを検索するオリジンのディレクトリパス。パスは、先頭をスラッシュ (/) にする必要があります。末尾をスラッシュ (/) にすることはできません。例えば、`example-path/` で終わることはできません。これを指定しない場合、割り当てられたオリジンのオリジンパスが使用されます。    
**カスタムオリジンの場合**  
パスは URL でエンコードし、255 文字以内で指定する必要があります。

**customHeaders (オプション）**  
各カスタムヘッダーの名前と値のペアを指定することで、カスタムヘッダーをリクエストに含めることができます。形式は、イベント構造のリクエストヘッダーおよびレスポンスヘッダーの形式とは異なります。次のキーと値のペアの構文を使用します。  

```
{"key1": "value1", "key2": "value2", ...}
```
許可されていないヘッダーは追加できません。また、同じ名前のヘッダーを受信リクエストの `headers` にも使用することはできません。関数コードでは、ヘッダー名を小文字にする必要があります。CloudFront Functions がイベントオブジェクトを HTTP リクエストに変換し直すと、ヘッダー名の各単語の先頭文字が大文字になり、各単語がハイフンで区切られます。  
例えば、関数コードが `example-header-name` というヘッダーを追加した場合、CloudFront は、これを HTTP リクエストで `Example-Header-Name` に変換します。詳細については、「[CloudFront でオリジンリクエストに追加できないカスタムヘッダー](add-origin-custom-headers.md#add-origin-custom-headers-denylist)」と「[エッジ関数に対する制限](edge-functions-restrictions.md)」を参照してください。  
これを指定しない場合、割り当てられたオリジンの任意のカスタムヘッダーが使用されます。

**connectionAttempts (オプション）**  
CloudFront がオリジンへの接続を試行する回数。最小値は 1、最大値は 3 です。これを指定しない場合、割り当てられたオリジンの接続試行が使用されます。

**originShield (オプション）**  
これにより、CloudFront Origin Shield を有効化または更新します。Origin Shield を使用すると、オリジンの負荷を軽減できます。詳細については、「[Amazon CloudFront Origin Shield の使用](origin-shield.md)」を参照してください。これを指定しない場合、割り当てられたオリジンの Origin Shield 設定が使用されます。    
**enabled (必須）**  
Origin Shield を有効または無効にするブール式。値として `true` または `false` を使用します。  
**region (有効にする場合は必須）**  
Origin Shield の AWS リージョン。オリジンへのレイテンシーが最も低い AWS リージョンを指定します。リージョン名ではなく、リージョンコードを使用します。例えば、米国東部 (オハイオ) リージョンを指定するには、`us-east-2` を使用します。  
CloudFront Origin Shield を有効にする場合は、AWS リージョンを指定する必要があります。利用可能な AWS リージョンのリストと、オリジンに最適なリージョンを選択する方法については、「[Origin Shield の AWS リージョンを選択する](origin-shield.md#choose-origin-shield-region)」を参照してください。

**originAccessControlConfig (オプション）**  
このオリジンのオリジンアクセスコントロール (OAC) の一意の識別子。オリジンが Amazon S3、Lambda 関数 URL、MediaStore、MediaPackage V2 などの CloudFront OAC をサポートしている場合にのみ使用されます。これを指定しない場合は、割り当てられたオリジンの OAC 設定が使用されます。  
レガシーオリジンアクセスアイデンティティ (OAI) はサポートされていません。詳細については、「[AWS オリジンへのアクセスを制限する](private-content-restricting-access-to-origin.md)」を参照してください。    
**enabled (必須）**  
OAC を有効または無効にするブール式。値として `true` または `false` を使用します。  
**signingBehavior (有効にする場合は必須）**  
CloudFront が署名する (認証情報を追加する) リクエストを指定します。最も一般的なユースケースには `always` を指定します。詳細については、「[オリジンアクセスコントロールの詳細設定](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3)」を参照してください。  
このフィールドには以下の値のいずれかがあります。  
+ `always` - CloudFront はすべてのオリジンリクエストに署名し、ビューワーリクエストの `Authorization` ヘッダーが存在する場合は上書きします。
+ `never` - CloudFront はオリジンリクエストに署名しません。この値は、オリジンのオリジンアクセスコントロールをオフにします。
+ `no-override` - ビューワーリクエストに `Authorization` ヘッダーが含まれていない場合、CloudFront はオリジンリクエストに署名します。ビューワーリクエストに `Authorization` ヘッダーが含まれている場合、CloudFront はオリジンリクエストに署名せず、代わりにビューワーリクエストから `Authorization` ヘッダーを渡します。
**警告**  
ビューワーリクエストから `Authorization` ヘッダーを渡すには、このオリジンアクセスコントロールに関連付けられているオリジンを使用するすべてのキャッシュ動作で、このヘッダーをオリジンリクエストポリシーに追加する必要があります。詳細については、「[ポリシーを使用してオリジンリクエストを制御する](controlling-origin-requests.md)」を参照してください。  
**signingProtocol (有効にする場合は必須）**  
OAC の署名プロトコル。CloudFront でリクエストを署名 (認証) する方法を決定します。唯一の有効な値は `sigv4` です。  
**originType (有効にする場合は必須）**  
この OAC のオリジンのタイプ。有効な値は、`s3`、`mediapackagev2`、`mediastore`、および `lambda` です。

**timeouts (オプション)**  
CloudFront がオリジンからの応答やデータ送信を待機する時間を指定できるタイムアウト。これを指定しない場合、割り当てられたオリジンのタイムアウト設定が使用されます。  
指定されていない限り、これらのタイムアウトはカスタムオリジンと Amazon S3 オリジンの両方をサポートします。  
**readTimeout (オプション)**  
`readTimeout` は、次の両方の値に適用されます。  
+ CloudFront がリクエストをオリジンに転送してからレスポンスを受け取るまでの待機時間 (秒)
+ CloudFront がオリジンからレスポンスのパケットを受け取ってから次のパケットを受け取るまでの待機時間 (秒) 
最小のタイムアウトは 1 秒、最大は 120 秒です。詳細については、「[応答タイムアウト](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout)」を参照してください。  
**responseCompletionTimeout (オプション)**  
CloudFront からオリジンへのリクエストを開いたままにして応答を待機できる時間 (秒単位)。この時間までにオリジンから完全な応答が受信されない場合、CloudFront は接続を終了します。  
`responseCompletionTimeout` の値は、`readTimeout` の値以上にする必要があります。詳細については、「[応答完了タイムアウト](DownloadDistValuesOrigin.md#response-completion-timeout)」を参照してください。  
**keepAliveTimeout (オプション)**  
このタイムアウトはカスタムオリジンにのみ適用され、Amazon S3 オリジンには適用されません (S3 オリジン設定では、これらの設定は無視されます。)   
`keepAliveTimeout` は、レスポンスの最後のパケットを受信した後、CloudFront がオリジンへの接続を維持しようとする時間を指定します。最小のタイムアウトは 1 秒、最大は 120 秒です。詳細については、「[キープアライブタイムアウト (カスタムオリジンおよび VPC オリジンのみ)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginKeepaliveTimeout)」を参照してください。  
**connectionTimeout (オプション）**  
オリジンへの接続を確立しようとするときに CloudFront が待機する秒数。最小のタイムアウトは 1 秒、最大は 10 秒です。詳細については、「[接続タイムアウト](DownloadDistValuesOrigin.md#origin-connection-timeout)」を参照してください。

**customOriginConfig (オプション）**  
`customOriginConfig` を使用して、Amazon S3 バケット*ではない*オリジンの接続設定を指定します。1 つの例外があります。S3 バケットが静的ウェブサイトホスティングで設定されている場合は、これらの設定を指定できます (他のタイプの S3 バケット設定では、これらの設定は無視されます)。`customOriginConfig` を指定しない場合、割り当てられたオリジンの設定が使用されます。    
**port (必須)**  
CloudFront がオリジンに接続するために使用する HTTP ポート。オリジンがリッスンしている HTTP ポートを指定します。  
**protocol (必須)**  
CloudFront がオリジンへの接続に使用するプロトコル (HTTP または HTTPS) を指定します。有効な値は次のとおりです。  
+ `http` – CloudFront は常に HTTP を使用してオリジンに接続します。
+ `https` – CloudFront は常に HTTPS を使用してオリジンに接続します。  
**sslProtocols (必須）**  
HTTPS 経由でオリジンに接続するときに CloudFront で使用する最小の SSL/TLS プロトコルを指定するリスト。有効な値は、`SSLv3`、`TLSv1`、`TLSv1.1`、および `TLSv1.2` です。詳細については、「[最小限のオリジン SSL プロトコル](DownloadDistValuesOrigin.md#DownloadDistValuesOriginSSLProtocols)」を参照してください。  
**ipAddressType (オプション)**  
CloudFront がオリジンへの接続に使用する IP アドレスタイプを指定します。有効な値は、`ipv4`、`ipv6`、および `dualstack` です。`ipAddressType` の変更は、`domainName` プロパティも変更される場合にのみサポートされます。

**sni (オプション、S3 カスタムオリジンでない場合)**  
Server Name Indication (SNI) は、TLS ハンドシェイクプロセスの開始時に接続しようとしているホスト名をクライアントが示す Transport Layer Security (TLS) プロトコルの拡張機能です。この値は、オリジンサーバーの TLS 証明書の共通名と一致している必要があります。それ以外の場合、オリジンサーバーがエラーをスローする可能性があります。  
これを指定しない場合、`hostHeader` パラメータの値が使用されます。ホストヘッダーが指定されない場合、`domainName` パラメータの値が使用されます。  
ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。SNI ではコロン (`:`) を使用できません。IP アドレスも使用できません。SNI は最大 253 文字です。

**allowedCertificateNames (オプション、S3 カスタムオリジンでない場合)**  
CloudFront が使用する有効な証明書名のリストを含めて、オリジンサーバーとの TLS ハンドシェイク中にオリジンサーバーの TLS 証明書のドメインマッチングを検証できます。このフィールドは有効なドメイン名の配列を想定しており、`*.example.com` などのワイルドカードドメインを含めることができます。  
最大 20 個の許可された証明書名を指定できます。それぞれの証明書名には最大 64 文字を使用できます。

**Example – Amazon S3 リクエストオリジンへの更新**  
次の例では、ビューワーリクエストのオリジンを S3 バケットに変更し、OAC を有効にして、オリジンに送信されたカスタムヘッダーをリセットします。  

```
cf.updateRequestOrigin({
    "domainName" : "amzn-s3-demo-bucket-in-us-east-1.s3.us-east-1.amazonaws.com",
    "originAccessControlConfig": {
        "enabled": true,
        "signingBehavior": "always",
        "signingProtocol": "sigv4",
        "originType": "s3"
    },
    // Empty object resets any header configured on the assigned origin
    "customHeaders": {}
});
```

**Example – Application Load Balancer リクエストオリジンへの更新**  
次の例では、ビューワーリクエストのオリジンを Application Load Balancer オリジンに変更し、カスタムヘッダーとタイムアウトを設定します。  

```
cf.updateRequestOrigin({
    "domainName" : "example-1234567890.us-east-1.elb.amazonaws.com",
    "timeouts": {
        "readTimeout": 30,
        "connectionTimeout": 5
    },
    "customHeaders": {
        "x-stage": "production",
        "x-region": "us-east-1"
    }
});
```

**Example – Origin Shield が有効になっているオリジンへの更新**  
次の例では、ディストリビューションのオリジンで Origin Shield が有効になっています。関数コードは、オリジンに使用されているドメイン名のみを更新し、他のすべてのオプションパラメータを省略します。この場合、Origin Shield パラメータは更新されていないため、Origin Shield は変更されたオリジンドメイン名で引き続き使用されます。  

```
cf.updateRequestOrigin({
    "domainName" : "www.example.com"
});
```

**Example - ホストヘッダー、SNI、および許可された証明書名を更新する**  
ほとんどのユースケースでは、オリジンへのリクエストにこのタイプの変更を使用する必要はありません。これらの値の変更による影響を理解していない限り、これらのパラメータを使用しないでください。
次の例では、ドメイン名、ホストヘッダー、SNI、およびオリジンへのリクエストで許可された証明書を変更します。  

```
cf.updateRequestOrigin({ 
    "domainName": "www.example.com", 
    "hostHeader": "test.example.com", 
    "sni": "test.example.net", 
    "allowedCertificateNames": ["*.example.com", "*.example.net"],
});
```

## selectRequestOriginById() メソッド
<a name="select-request-origin-id-helper-function"></a>

ディストリビューションで既に設定されている別のオリジンを選択して、既存のオリジンを更新するには、`selectRequestOriginById()` を使用します。このメソッドは、更新されたオリジンで定義されているすべての設定を使用します。

このメソッドは、関数の実行時に使用されたのと同じディストリビューションで既に定義されているオリジンのみを受け入れます。オリジンは、オリジンの設定時に定義したオリジン名であるオリジン ID によって参照されます。

ディストリビューション内で VPC オリジンが設定されている場合は、このメソッドを使用してオリジンを VPC オリジンに更新できます。詳細については、「[VPC オリジンを使用したアクセス制限](private-content-vpc-origins.md)」を参照してください。

**注意事項**  
`selectRequestOriginById()` 関数は、相互 TLS (オリジン) が有効になっているオリジンを選択できません。この関数を使用して相互 TLS (オリジン) 対応オリジンを選択しようとすると、検証エラーが発生します。
ユースケースで相互 TLS (オリジン) を使用した動的オリジン選択が必要な場合は、代わりに `updateRequestOrigin()` を使用し、すべてのターゲットオリジンが同じクライアント証明書を使用していることを確認します。

**[リクエスト**]

```
cf.selectRequestOriginById(origin_id, {origin_overrides})
```

前の例では、`origin_id` は、関数を実行しているディストリビューション内のオリジンのオリジン名を指す文字列です。`origin_overrides ` パラメータには、次を含めることができます。

**hostHeader (オプション、S3 カスタムオリジンでない場合)**  
オリジンにリクエストをするときに使用するホストヘッダー。これを指定しない場合、`domainName` パラメータの値が使用されます。  
ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。ホストヘッダーではコロン (`:`) を使用できません。IP アドレスも使用できません。ホストヘッダーは最大 253 文字です。

**sni (オプション、S3 カスタムオリジンでない場合)**  
Server Name Indication (SNI) は、TLS ハンドシェイクプロセスの開始時に接続しようとしているホスト名をクライアントが示す Transport Layer Security (TLS) プロトコルの拡張機能です。この値は、オリジンサーバーの TLS 証明書の共通名と一致している必要があります。それ以外の場合、オリジンサーバーがエラーをスローする可能性があります。  
これを指定しない場合、`hostHeader` パラメータの値が使用されます。ホストヘッダーが指定されない場合、`domainName` パラメータの値が使用されます。  
ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。SNI ではコロン (`:`) を使用できません。IP アドレスも使用できません。SNI は最大 253 文字です。

**allowedCertificateNames (オプション、S3 カスタムオリジンでない場合)**  
CloudFront が使用する有効な証明書名のリストを含めて、オリジンサーバーとの TLS ハンドシェイク中にオリジンサーバーの TLS 証明書のドメインマッチングを検証できます。このフィールドは有効なドメイン名の配列を想定しており、`*.example.com` などのワイルドカードドメインを含めることができます。  
最大 20 個の許可された証明書名を指定できます。それぞれの証明書名には最大 64 文字を使用できます。

**[リクエスト**]

```
selectRequestOriginById(origin_id)
```

前の例では、`origin_id` は、関数を実行しているディストリビューション内のオリジンのオリジン名を指す文字列です。

**Example – Amazon S3 リクエストオリジンを選択する**  
次の例では、ディストリビューションに関連付けられたオリジンのリストから `amzn-s3-demo-bucket-in-us-east-1` という名前のオリジンを選択し、`amzn-s3-demo-bucket-in-us-east-1` オリジンの設定をリクエストに適用します。  

```
cf.selectRequestOriginById("amzn-s3-demo-bucket-in-us-east-1");
```

**Example – Application Load Balancer リクエストオリジンを選択する**  
次の例では、ディストリビューションに関連付けられたオリジンのリストから `myALB-prod` という名前の Application Load Balancer オリジンを選択し、`myALB-prod` の設定をリクエストに適用します。  

```
cf.selectRequestOriginById("myALB-prod");
```

**Example - Application Load Balancer リクエストオリジンを選択し、ホストヘッダーを上書きする**  
前の例のように、次の例ではディストリビューションに関連付けられたオリジンのリストから `myALB-prod` という名前の Application Load Balancer オリジンを選択し、`myALB-prod` の設定をリクエストに適用します。ただし、この例では、`origin_overrides` を使用してホストヘッダー値を上書きします。  

```
cf.overrideRequestOrigin("myALB-prod",{ 
        "hostHeader" : "test.example.com"
});
```

## createRequestOriginGroup() メソッド
<a name="create-request-origin-group-helper-function"></a>

`createRequestOriginGroup()` を使用して、高可用性を必要とするシナリオでフェイルオーバー用の[オリジングループ](high_availability_origin_failover.md#concept_origin_groups.creating)として使用する 2 つのオリジンを定義します。

オリジングループには、2 つのオリジン (プライマリとセカンダリ) と指定したフェイルオーバー基準が含まれます。CloudFront でオリジンフェイルオーバーをサポートするオリジングループを作成します。このメソッドを使用してオリジングループを作成または更新する際に、単一のオリジンではなくオリジングループを指定できます。CloudFront は、フェイルオーバー基準を使用して、プライマリオリジンからセカンダリオリジンにフェイルオーバーします。

ディストリビューションに VPC オリジンが設定されている場合は、このメソッドを使用して、VPC オリジンを使用したオリジングループを作成できます。詳細については、「[VPC オリジンを使用したアクセス制限](private-content-vpc-origins.md)」を参照してください。

**注意事項**  
`createRequestOriginGroup()` 関数は、相互 TLS (オリジン) が有効なオリジンを含むオリジングループの作成をサポートしていません。相互 TLS (オリジン) オリジンを持つオリジングループは、CloudFront Functions を介して動的に作成することはできません。
Mutual TLS (オリジン) でオリジンフェイルオーバー機能が必要な場合は、関数で動的に作成するのではなく、CloudFront ディストリビューション設定でオリジングループを直接設定します。

### リクエスト
<a name="create-origin-group-request"></a>

```
createRequestOriginGroup({origin_group_properties})
```

上記の例で、`origin_group_properties` には以下を含めることができます。

**originIds (必須）**  
`origin_ids` の配列。`origin_id` は、関数を実行するディストリビューション内のオリジンのオリジン名を指す文字列です。配列の一部として 2 つのオリジンを指定する必要があります。リストの最初のオリジンはプライマリオリジンで、2 番目のオリジンはフェイルオーバー用のセカンダリオリジンとして機能します。

**originOverrides (オプション)**  
 `{origin_overrides}` パラメータを使用して、いくつかの詳細設定を上書きできます。`origin overrides` には、以下を含めることができます。    
**hostHeader (オプション、S3 カスタムオリジンでない場合)**  
オリジンにリクエストをするときに使用するホストヘッダー。これを指定しない場合、`domainName` パラメータの値が使用されます。  
ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。ホストヘッダーではコロン (`:`) を使用できません。IP アドレスも使用できません。ホストヘッダーは最大 253 文字です。  
**sni (オプション、S3 カスタムオリジンでない場合)**  
Server Name Indication (SNI) は、TLS ハンドシェイクプロセスの開始時に接続しようとしているホスト名をクライアントが示す Transport Layer Security (TLS) プロトコルの拡張機能です。この値は、オリジンサーバーの TLS 証明書の共通名と一致している必要があり、それ以外の場合、オリジンサーバーがエラーをスローする可能性があります。  
これを指定しない場合、`hostHeader` パラメータの値が使用されます。ホストヘッダーが指定されない場合、`domainName` パラメータの値が使用されます。  
ホストヘッダーまたはドメイン名パラメータのどちらも指定されていない場合、割り当てられたオリジンのドメイン名が使用されます。また、Forward to Origin (FTO) ポリシーにホストが含まれている場合は、受信リクエストのホストヘッダーが使用されます。SNI ではコロン (`:`) を使用できません。IP アドレスも使用できません。SNI は最大 253 文字です。  
**allowedCertificateNames (オプション、S3 カスタムオリジンでない場合)**  
CloudFront が使用する有効な証明書名のリストを含めて、オリジンサーバーとの TLS ハンドシェイク中にオリジンサーバーの TLS 証明書のドメインマッチングを検証できます。このフィールドは有効なドメイン名の配列を想定しており、`*.example.com` などのワイルドカードドメインを含めることができます。  
最大 20 個の許可された証明書名を指定できます。それぞれの証明書名には最大 64 文字を使用できます。

**selectionCriteria (オプション)**  
`default` オリジンフェイルオーバー条件を使用するか、`media-quality-score` ベースのフェイルオーバーロジックを使用するかを選択します。有効な値は次のとおりです。  
+ `default` は、`failoverCriteria` で指定されたステータスコードに基づいてフェイルオーバー基準を使用します。関数で `selectionCriteria` を設定しない場合、`default` が使用されます。
+ `media-quality-score` は、メディア対応ルーティング機能を使用している場合に使用されます。

**failoverCriteria (必須）**  
プライマリオリジンから返されたステータスコードの配列。このステータスコードが返されると、CloudFront はセカンダリオリジンへのフェイルオーバーをトリガーします。既存のオリジングループを上書きすると、この配列はオリジングループの元の設定で設定されたすべてのフェイルオーバーステータスコードを上書きします。  
`media-quality-score` `selectionCriteria` を使用すると、CloudFront はメディア品質スコアに基づいてリクエストのルーティングを試みます。選択されたオリジンがこの配列に設定されているエラーコードを返した場合、CloudFront は他のオリジンにフェイルオーバーします。

**Example – リクエストオリジングループを作成する**  
次の例では、オリジン ID を使用してリクエストのオリジングループを作成します。これらのオリジン ID は、この関数の実行に使用されるディストリビューションのオリジングループ設定から取得されます。  
必要に応じて、`originOverrides` を使用して、`sni`、`hostHeader`、`allowedCertificateNames` のオリジングループ設定を上書きできます。  

```
import cf from 'cloudfront';

function handler(event) {
    cf.createRequestOriginGroup({
        "originIds": [
            {
                "originId": "origin-1",
                "originOverrides": {
                    "hostHeader": "hostHeader.example.com",
                    "sni": "sni.example.com",
                    "allowedCertificateNames": ["cert1.example.com", "cert2.example.com", "cert3.example.com"]
                }
            },
            {
                "originId": "origin-2",
                "originOverrides": {
                    "hostHeader": "hostHeader2.example.com",
                    "sni": "sni2.example.com",
                    "allowedCertificateNames": ["cert4.example.com", "cert5.example.com"]
                }
            }
        ],
        "failoverCriteria": {
            "statusCodes": [500]
        }
    });
    
    event.request.headers['x-hookx'] = { value: 'origin-overrides' };
    return event.request;
}
```

# CloudFront SaaS Manager プロパティのヘルパーメソッド
<a name="saas-specific-logic-function-code"></a>

CloudFront SaaS Manager の次のヘルパー関数を使用して、作成した関数内のマルチテナントディストリビューションの値を取得します。このページの例を使用するには、まず JavaScript ランタイム 2.0 を使用して CloudFront 関数を作成する必要があります。詳細については、[CloudFront Functions の JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md) を参照してください。

**Topics**
+ [接続グループ](#connection-groups-helper-function)
+ [ディストリビューションテナント](#distribution-tenants-helper-functions)

## 接続グループ
<a name="connection-groups-helper-function"></a>

ディストリビューションテナントに関連付けられている接続グループにはドメイン名があります。

この値を取得するには、イベントオブジェクトの `context` サブオブジェクトの `endpoint` フィールドを使用します。

**[リクエスト**]

```
const value = event.context.endpoint;
```

**レスポンス**

レスポンスは、d111111abcdef8.cloudfront.net などの接続グループのドメイン名を含む `string` です。`endpoint` フィールドは、関連付けられた接続グループを持つマルチテナントディストリビューションに対して関数が呼び出された場合にのみ表示されます。詳細については、「[コンテキストオブジェクト](functions-event-structure.md#functions-event-structure-context)」を参照してください。

## ディストリビューションテナント
<a name="distribution-tenants-helper-functions"></a>

CloudFront Functions には、特定のディストリビューションテナント値へのアクセスを提供するモジュールがあります。

このモジュールを使用するには、関数コードの最初の行に、次のステートメントを含めます。

```
import cf from 'cloudfront';
```

次の例は、直接またはネストされた呼び出し関数を介して、`handler` 関数でのみ使用できます。

### `distributionTenant.id` フィールド
<a name="distribution-tenants-field"></a>

このフィールドを使用して、ディストリビューションテナント ID の値を取得します。

**[リクエスト**]

```
const value = cf.distributionTenant.id;
```

**レスポンス**

レスポンスは、`dt_1a2b3c4d5e6f7` などのディストリビューションテナント ID を含む `string` です。

**エラー処理**

関数が標準ディストリビューションに対して呼び出された場合、`distributionTenant.id` フィールドを指定すると `distributionTenant module is not available` 型エラーが返されます。このユースケースを処理するには、コードに `try` および `catch` ブロックを追加できます。

### `distributionTenant.parameters.get()` 方法
<a name="distribution-tenant-parameters-get-method"></a>

このメソッドを使用して、指定したディストリビューションテナントパラメータ名の値を返します。

```
distributionTenant.parameters.get("key");
```

`key`: 値を取得するディストリビューションテナントパラメータ名。

**[リクエスト]**

```
const value = distributionTenant.parameters.get("key");
```

**応答**

レスポンスは、ディストリビューションテナントパラメータの値を含む `string` です。例えば、キー名が `TenantPath` の場合、このパラメータの値は `tenant1` になります。

**エラー処理**

次のエラーが表示される場合があります。
+ 関数が標準ディストリビューションに対して呼び出された場合、`distributionTenant.parameters.get()` メソッドは `distributionTenant module is not available` 型エラーを返します。
+ 指定したディストリビューションテナントパラメータが存在しない場合は、`DistributionTenantParameterKeyNotFound` エラーが返されます。

これらのユースケースを管理するには、コードに `try` および `catch` ブロックを追加できます。

# async および await を使用します。
<a name="async-await-syntax"></a>

CloudFront Functions JavaScript ランタイム関数 2.0 には、`Promise` オブジェクトを処理するための `async` および `await` 構文が用意されています。Promise は遅延した結果を表し、`async` とマークされた関数のキーワード `await` を使用してアクセスできます。さまざまな新しい WebCrypto 関数が Promise を使用しています。

`Promise` オブジェクトの詳細については、「[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)」を参照してください。

**注記**  
次のコードサンプルでは、JavaScript ランタイム 2.0 を使用する必要があります。  
`await` は `async` 関数内でのみ使用できます。`async` 引数とクロージャはサポートされていません。

```
async function answer() {
    return 42;
}

// Note: async, await can be used only inside an async function. async arguments and closures are not supported.

async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

次の JavaScript コード例は、`then` チェーンメソッドを使用して Promise を表示する方法を示しています。`catch` を使用してエラーを表示できます。

**警告**  
promise コンビネーター (例: `Promise.all`、`Promise.any`、および promise チェーンメソッド (例: `then` および `catch`) を使用すると、関数のメモリ使用量が高くなる可能性があります。関数が[最大関数メモリ](cloudfront-limits.md#limits-functions)クォータを超えると、実行に失敗します。このエラーを回避するには、`promise` メソッドの代わりに `await` 構文を使用することをお勧めします。

```
async function answer() {
    return 42;
}

async function squared_answer() {
   return answer().then(value => value * value)
} 
// Note: async, await can be used only inside an async function. async arguments and closures are not supported.
async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await squared_answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

# CloudFront Functions の CWT サポート
<a name="cwt-support-cloudfront-functions"></a>

このセクションでは、CloudFront Functions での CBOR ウェブトークン (CWT) のサポートについて詳しく説明します。これにより、CloudFront Edge Locations での安全なトークンベースの認証と承認が可能になります。このサポートはモジュールとして提供され、CloudFront Functions でアクセスできます。

このモジュールを使用するには、JavaScript ランタイム 2.0 を使用して CloudFront Functions を作成し、関数コードの最初の行に次のステートメントを含めます。

```
import cf from 'cloudfront';
```

このモジュールに関連付けられたメソッドには、次からアクセスできます (\$1 はモジュール内に存在するさまざまな関数を表すワイルドカードです)。

```
cf.cwt.*
```

詳細については、「[CloudFront Functions の JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md)」を参照してください。

現在、モジュールは HS256 (HMAC-SHA256) アルゴリズムを使用した MAC0 構造のみをサポートし、トークンの最大サイズは 1KB に制限されています。

## トークン構造
<a name="token-structure"></a>

このセクションでは、CWT モジュールで想定されるトークン構造について説明します。モジュールは、トークンが正しくタグ付けされ、識別可能であること (COSE MAC0 など) を想定しています。さらに、トークンの構造については、モジュールは [CBOR Object Signing and Encryption (COSE) [RFC 8152]](https://datatracker.ietf.org/doc/html/rfc8152) によって設定された標準に従います。

```
( // CWT Tag (Tag value: 61) --- optional    
    ( // COSE MAC0 Structure Tag (Tag value: 17) --- required        
        [            
            protectedHeaders,            
            unprotectedHeaders,            
            payload,            
            tag,        
        ]    
    )
)
```

**Example : COSE MAC0 構造を使用する CWT**  

```
61( // CWT tag     
    17( // COSE_MAC0 tag       
        [         
            { // Protected Headers           
                1: 4  // algorithm : HMAC-256-64         
            },         
            { // Unprotected Headers           
                4: h'53796d6d6574726963323536' // kid : Symmetric key id          
            },         
            { // Payload           
                1: "https://iss.example.com", // iss           
                2: "exampleUser", // sub           
                3: "https://aud.example.com", // aud           
                4: 1444064944, // exp           
                5: 1443944944, // nbf           
                6: 1443944944, // iat         
            },         
            h'093101ef6d789200' // tag       
        ]     
    )   
)
```
トークンを生成する場合、CWT タグはオプションです。ただし、COSE 構造タグは必要です。

## validateToken() メソッド
<a name="validatetoken-method"></a>

関数は、指定されたキーを使用して CWT トークンをデコードし、検証します。検証が成功すると、デコードされた CWT トークンが返されます。それ以外の場合は、エラーをスローします。この関数はクレームセットを検証しないことに注意してください。

### リクエスト
<a name="validatetoken-request"></a>

```
cf.cwt.validateToken(token, handlerContext{key})
```パラメータ

**トークン (必須)**  
検証用のエンコードされたトークン。これは JavaScript バッファである必要があります。

**handlerContext (必須)**  
validateToken 呼び出しのコンテキストを保存する JavaScript オブジェクト。現在、 キープロパティのみがサポートされています。

**キー (必須)**  
メッセージダイジェストの計算のシークレットキー。文字列または JavaScript バッファのいずれかとして指定できます。

### 応答
<a name="validatetoken-response"></a>

`validateToken()` メソッドが正常に検証されたトークンを返すと、関数からのレスポンスは次の形式の `CWTObject` になります。デコードされると、すべてのクレームキーが文字列として表されます。

```
CWTObject {    
    protectedHeaders,    
    unprotectedHeaders,    
    payload
}
```

### 例 – トークンの一部として送信された kid を使用してトークンを検証します
<a name="validatetoken-example"></a>

この例では、kid がヘッダーから抽出される CWT トークンの検証を示しています。その後、kid は CloudFront Functions KeyValueStore に渡され、トークンの検証に使用されるシークレットキーを取得します。

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
                
        // Retrieve the secret key from the kvs
        let secretKey = await cf.kvs().get(kid);
                 
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtObj = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtObj[CwtClaims.exp] && cwtObj[CwtClaims.exp] < currentTime) {
                return {
                    statusCode: 401,
                    statusDescription: 'Token expired'
                };
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

## generateToken() メソッド
<a name="generatetoken-method"></a>

この関数は、提供されたペイロードとコンテキスト設定を使用して新しい CWT トークンを生成します。

### リクエスト
<a name="generatetoken-request"></a>

```
cf.cwt.generateToken(generatorContext, payload)
```パラメータ

**generatorContext (必須)**  
これは、トークンを生成するためのコンテキストとして使用される JavaScript オブジェクトで、次のキーと値のペアを含みます。    
**cwtTag (オプション)**  
この値はブール値であり、`true` が指定されている場合は `cwtTag` を追加する必要があります。  
**coseTag (必須)**  
COSE タグタイプを指定します。現在のところ、`MAC0` のみサポートされます。  
**キー (必須)**  
メッセージダイジェストを計算するシークレットキー。この値は、文字列または JavaScript `Buffer` のいずれかです。

**ペイロード (必須)**  
エンコード用のトークンペイロード。ペイロードは `CWTObject` 形式である必要があります。

### 応答
<a name="generatetoken-response"></a>

エンコードされたトークンを含む JavaScript バッファを返します。

**Example : CWT トークンを生成する**  

```
import cf from 'cloudfront';

const CwtClaims = {
    iss: 1,
    sub: 2,
    exp: 4
};

const CatClaims = {
    catu: 401,
    catnip: 402,
    catm: 403,
    catr: 404
};

const Catu = {
    host: 1,
    path: 2,
    ext: 3
};

const CatuMatchTypes = {
    prefix_match: 1,
    suffix_match: 2,
    exact_match: 3
};

const Catr = {
    renewal_method: 1,
    next_renewal_time: 2,
    max_uses: 3
};

async function handler(event) {
    try {
        const response = {
            statusCode: 200,
            statusDescription: 'OK',
            headers: {}
        };
        
        const commonAccessToken = {
            protected: {
                1: "5",
            },
            unprotected: {},
            payload: {
                [CwtClaims.iss]: "cloudfront-documentation",
                [CwtClaims.sub]: "cwt-support-on-cloudfront-functions",
                [CwtClaims.exp]: 1740000000,
                [CatClaims.catu]: {
                    [Catu.host]: {
                        [CatuMatchTypes.suffix_match]: ".cloudfront.net"
                    },
                    [Catu.path]: {
                        [CatuMatchTypes.prefix_match]: "/media/live-stream/cf-4k/"
                    },
                    [Catu.ext]: {
                        [CatuMatchTypes.exact_match]: [
                            ".m3u8",
                            ".ts",
                            ".mpd"
                        ]
                    }
                },
                [CatClaims.catnip]: [
                    "[IP_ADDRESS]",
                    "[IP_ADDRESS]"
                ],
                [CatClaims.catm]: [
                    "GET",
                    "HEAD"
                ],
                [CatClaims.catr]: {
                    [Catr.renewal_method]: "header_renewal",
                    [Catr.next_renewal_time]: 1750000000,
                    [Catr.max_uses]: 5
                }
            }
        };
        
        if (!request.headers['x-cwt-kid']) {
            throw new Error('Missing x-cwt-kid header');
        }
        
        const kid = request.headers['x-cwt-kid'].value;
        const secretKey = await cf.kvs().get(kid);
        
        if (!secretKey) {
            throw new Error('Secret key not found for provided kid');
        }
        
        try {
            const genContext = {
                cwtTag: true,
                coseTag: "MAC0",
                key: secretKey
            };
            
            const tokenBuffer = cf.cwt.generateToken(commonAccessToken, genContext);
            response.headers['x-generated-cwt-token'] = { value: tokenBuffer.toString('base64url') };
                        
            return response;
        } catch (tokenError) {
            return {
                statusCode: 401,
                statusDescription: 'Could not generate the token'
            };
        }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
    }
}
```

**Example : 一部のロジックに基づいてトークンを更新する**  

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
        let secretKey = await cf.kvs().get(kid); // Retrieve the secret key from the kvs
                
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtJSON = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtJSON[CwtClaims.exp] && cwtJSON[CwtClaims.exp] < currentTime) {
                // We can regnerate the token and add 8 hours to the expiry time
                cwtJSON[CwtClaims.exp] = Math.floor(Date.now() / 1000) + (8 * 60 * 60);
                                
                let genContext = {
                  coseTag: "MAC0",
                  key: secretKey
                }
                                
                let newTokenBuffer = cf.cwt.generateToken(cwtJSON, genContext);
                 request.headers['x-cwt-regenerated-token'] = newTokenBuffer.toString('base64url');
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    }
    catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

# 一般的なヘルパーメソッド
<a name="general-helper-methods"></a>

このページでは、CloudFront Functions 内の追加のヘルパーメソッドについて説明します。これらのメソッドを使用するには、JavaScript ランタイム 2.0 を使用して CloudFront 関数を作成します。

```
import cf from 'cloudfront';
```

詳細については、「[CloudFront Functions の JavaScript ランタイム 2.0 の機能](functions-javascript-runtime-20.md)」を参照してください。

## `edgeLocation` メタデータ
<a name="edge-location-metadata"></a>

このメソッドは、`cloudfront` モジュールの使用が必要です。

**注記**  
このメソッドは、ビューワーリクエスト関数にのみ使用できます。ビューワーレスポンス関数の場合、このメソッドは空です。

この JavaScript オブジェクトを使用して、エッジロケーションの空港コード、予想される[リージョナルエッジキャッシュ](HowCloudFrontWorks.md#CloudFrontRegionaledgecaches)リージョン、またはリクエストの処理に使用される CloudFront サーバーの IP アドレスを取得します。このメタデータは、ビューワーリクエストイベントトリガーでのみ使用できます。

```
cf.edgeLocation = {
    name: SEA
    serverIp: 1.2.3.4
    region: us-west-2
}
```

`cf.edgeLocation` オブジェクトには、以下を含めることができます。

**名前**  
リクエストを処理したエッジロケーションの 3 文字の [IATA コード](https://en.wikipedia.org/wiki/IATA_airport_code)。

**serverIp**  
リクエストを処理したサーバーの IPv4 または IPv6 アドレス。

**リージョン**  
キャッシュミスがある場合にリクエストが使用すると*予想される* CloudFront Regional Edge Cache (REC)。予想される REC が使用できず、バックアップ REC がリクエストに使用される場合、この値は更新されません。プライマリ REC と Origin Shield が同じ場所である場合を除き、これには使用されている Origin Shield の場所は含まれません。

**注記**  
CloudFront がオリジンフェイルオーバーを使用するように設定されている場合、CloudFront Functions は 2 回目は呼び出されません。詳細については、「[CloudFront オリジンフェイルオーバーを使用して高可用性を最適化する](high_availability_origin_failover.md)」を参照してください。

## `rawQueryString()` 方法
<a name="raw-query-string-method"></a>

このメソッドに、`cloudFront` モジュールは必要ありません。

`rawQueryString()` メソッドを使用して、解析されていない未変更のクエリ文字列を文字列として取得します。

**[リクエスト**]

```
function handler(event) {
    var request = event.request;
    const qs = request.rawQueryString();
}
```

**レスポンス**

先頭の `?` なしで、受信リクエストの完全なクエリ文字列を文字列値として返します。
+ クエリ文字列はないが、`?` が存在する場合、関数は空の文字列を返します。
+ クエリ文字列がなく、`?` が存在しない場合、関数は `undefined` を返します。

**ケース 1: 完全なクエリ文字列が返された (先頭に `?` なし)**  
受信リクエスト URL: `https://example.com/page?name=John&age=25&city=Boston`  
`rawQueryString()`戻り値 。`"name=John&age=25&city=Boston"`

**ケース 2: 空の文字列が返された (`?` は存在するが、パラメータがない場合)**  
受信リクエスト URL: `https://example.com/page?`  
`rawQueryString()`戻り値 。`""`

**ケース 3: `undefined` が返された (クエリ文字列および `?` なし)**  
受信リクエスト URL: `https://example.com/page`  
`rawQueryString()`戻り値 。`undefined`

# 関数を作成する
<a name="create-function"></a>

関数は 2 段階で作成します。

1. 関数コードを JavaScript として作成します。CloudFront コンソールのデフォルトの例を使用することも、独自に記述することもできます。詳細については、以下の各トピックを参照してください。
   + [関数コードを記述する](writing-function-code.md)
   + [CloudFront Functions のイベント構造](functions-event-structure.md)
   + [CloudFront の CloudFront Functions の例](service_code_examples_cloudfront_functions_examples.md)

1. CloudFront を使用して関数を作成し、コードを含めます。コードは関数内にあります (リファレンスとしてではありません)。

------
#### [ Console ]

**関数を作成するには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

1. [**Create function** (関数の作成)] を選択します。

1. AWS アカウント内での一意な関数名を入力し、Java Script バージョンを選択して、**[続行]** を選択します。新しい関数の詳細ページが表示されます。
**注記**  
関数で [[キーと値のペア]](kvs-with-functions.md) を使用する場合は、Java Script ランタイム 2.0 を選択する必要があります。

1. **[関数コード]** セクションで、**[ビルド]** タブを選択し、関数コードを入力します。**[ビルド]** タブに含まれるサンプルコードは、関数コードの基本的な構文を示しています。

1. [**Save changes**] (変更の保存) をクリックします。

1. 関数コードでキーと値のペアを使用する場合は、キー値ストアを関連付ける必要があります。

   キー値ストアは、関数の作成時に関連付けることができます。または、後で[関数を更新](update-function.md)して関連付けることもできます。

   キーと値のストアを今すぐ関連付けるには、次の手順に従います。
   + **[KeyValueStore を関連付け]** セクションに移動して、**[既存の KeyValueStore を関連付け]** を選択します。
   + 関数のキーと値のペアを含むキーバリューストアを選択し、**[KeyValueStore を関連付ける]** を選択します。

   CloudFront はストアを直ちに関数に関連付けます。関数を保存する必要はありません。

------
#### [ CLI ]

CLI を使用する場合、通常は最初に関数コードをファイルに作成し、次に AWS CLI を使用して関数を作成します。

**関数を作成するには**

1. 関数コードをファイルに作成し、コンピュータが接続できるディレクトリに保存します。

1. 次の例に示すようにコマンドを実行します。この例では、`fileb://` 表記を使用してファイルを渡します。コマンドを読みやすくするために改行も含まれています。

   ```
   aws cloudfront create-function \
       --name MaxAge \
       --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"}]}}' \
       --function-code fileb://function-max-age-v1.js
   ```
**メモ**  
`Runtime` – Java Script のバージョン。関数で[キーと値のペア](kvs-with-functions.md)を使用するには、バージョン 2.0 を指定する必要があります。
`KeyValueStoreAssociations` – 関数がキーと値のペアを使用する場合、関数の初回作成時にキー値ストアを関連付けることができます。または、`update-function` を使用して後で関連付けることもできます。各関数に関連付けることができるキー値ストアは 1 つだけのため、`Quantity` は常に `1` です。

   コマンドが成功した場合は、以下のような出力が表示されます。

   ```
   ETag: ETVABCEXAMPLE
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years
       Runtime: cloudfront-js-2.0
       KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
     FunctionMetadata:
       CreatedTime: '2021-04-18T20:38:56.915000+00:00'
       FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge
       LastModifiedTime: '2023-11-19T20:38:56.915000+00:00'
       Stage: DEVELOPMENT
     Name: MaxAge
     Status: UNPUBLISHED
   Location: https://cloudfront.amazonaws.com/2020-05-31/function/arn:aws:cloudfront:::function/MaxAge
   ```

   ほとんどの情報はリクエストから繰り返されます。その他の情報は CloudFront によって追加されます。
**メモ**  
`ETag` – この値は、キー値ストアを変更するたびに変わります。この値と関数名を使用して、以後、この関数を参照します。必ず現在の `ETag` を使用してください。
`FunctionARN` – CloudFront 関数の ARN。
111122223333 – AWS アカウント。
`Stage` – 関数のステージ (`LIVE` または `DEVELOPMENT`）。
`Status` – 関数のステータス (`PUBLISHED` または `UNPUBLISHED`)。

------

関数を作成すると、`DEVELOPMENT` ステージに追加されます。関数は、[テスト](test-function.md)してから[発行](publish-function.md)することをお勧めします。関数を発行すると、関数のステージは `LIVE` に変わります。

# 関数をテストする
<a name="test-function"></a>

関数をライブステージ (本番環境) にデプロイする前に、テストして期待どおりに動作することを確認できます。関数をテストするには、CloudFront ディストリビューションが本番環境で受信する可能性がある HTTP リクエストやレスポンスを表すイベントオブジェクトを指定します。**

CloudFront Functions は以下の処理を行います。

1. 指定されたイベントオブジェクトを入力として使用して、関数を実行します。

1. 関数の結果 (変更されたイベントオブジェクト) を、関数ログまたはエラーメッセージ、および関数の*コンピューティング使用率*とともに返します。コンピューティング使用率の詳細については、「[コンピューティング使用率を理解する](#compute-utilization)」を参照してください。

**注記**  
関数をテストすると、CloudFront は関数実行エラーのみを検証します。CloudFront は、リクエストが一度発行されると、正常に流れるかどうかは検証しません。例えば、関数が必須ヘッダーを削除しても、コードには問題がないため、テストは成功します。ただし、関数を発行してディストリビューションに関連付けると、CloudFront を介してリクエストが行われたときに関数は失敗します。

**Contents**
+ [イベントオブジェクトをセットアップする](#test-function-create-event)
+ [関数をテストする](#test-function-step-test)
+ [コンピューティング使用率を理解する](#compute-utilization)

## イベントオブジェクトをセットアップする
<a name="test-function-create-event"></a>

関数をテストする前に、テストに使用するイベントオブジェクトをセットアップする必要があります。これには複数のオプションがあります。

**オプション 1: イベントオブジェクトを保存せずにセットアップする**  
CloudFront コンソールのビジュアルエディターでイベントオブジェクトをセットアップしても、保存はできません。  
このイベントオブジェクトを使用して、保存されていなくても CloudFront コンソールから関数をテストできます。

**オプション 2: ビジュアルエディターでイベントオブジェクトを作成する**  
CloudFront コンソールのビジュアルエディターでイベントオブジェクトをセットアップしても、保存はできません。関数ごとに 10 個のイベントオブジェクトを作成して、例えば、考えられるさまざまな入力をテストできます。  
この方法でイベントオブジェクトを作成すると、イベントオブジェクトを使用して CloudFront コンソールで関数をテストできます。AWS API や SDK を使用して関数をテストする場合には使用できません。

**オプション 3: テキストエディターを使用してイベントオブジェクトを作成する**  
テキストエディターを使用して、イベントオブジェクトを JSON 形式で作成できます。イベントオブジェクトの構造については、「[イベントの構造](functions-event-structure.md)」を参照してください。  
このイベントオブジェクトを使用して、CLI で関数をテストできます。ただし、これを使用して CloudFront コンソールで関数をテストすることはできません。

**イベントオブジェクトを作成するには (オプション 1 または 2)**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

   テストする関数を選択します。

1. 関数の詳細ページで、**[テスト]** タブを選択します。

1. **[イベントタイプ]** で、以下のいずれかのオプションを選択します。
   + 関数が HTTP リクエストを変更したり、リクエストに基づいてレスポンスを生成する場合は、**[ビューワーリクエスト]** を選択します。**[リクエスト]** セクションが表示されます。
   + **[ビューアーレスポンス]** を選択します。**[リクエスト]** セクションと **[レスポンス]** セクションが表示されます。

1. イベントに含めるフィールドに入力します。**[JSON を編集]** を選択すると、未加工の JSON を表示できます。

1. (オプション) イベントを保存するには、**[保存]** を選択し、**[テストイベントを保存]** に名前を入力して **[保存]** を選択します。

   **[JSON を編集]** を選択し、未加工の JSON をコピーして、CloudFront 外の独自のファイルに保存することもできます。

**イベントオブジェクトを作成するには (オプション 3)**

テキストエディタを使用してイベントオブジェクトを作成します。このファイルは、コンピューターが接続できるディレクトリに保存します。

以下のガイドラインに確実に従ってください。
+ `distributionDomainName`、`distributionId`、`requestId` の各フィールドは省略します。
+ ヘッダー、Cookie、クエリ文字列の名前は必ず小文字にします。

この方法でイベントオブジェクトを作成する方法の 1 つは、ビジュアルエディターを使用してサンプルを作成することです。サンプルが正しいフォーマットになっていることを確認できます。そして、未加工の JSON をコピーし、テキストエディターに貼り付け、ファイルを保存することができます。

イベントの構造の詳細については、「[イベントの構造](functions-event-structure.md)」を参照してください。

## 関数をテストする
<a name="test-function-step-test"></a>

関数は、CloudFront コンソールまたは AWS Command Line Interface (AWS CLI) を使用してテストできます。

------
#### [ Console ]

**関数をテストするには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

1. テストする関数を選択します。

1. **[テスト]** タブを選択します。

1. 正しいイベントが表示されていることを確認します。現在表示されているイベントから切り替えるには、**[テストイベントを選択]** フィールドで別のイベントを選択します。

1. **[関数をテスト]** を選択します。コンソールに、関数ログとコンピューティング使用率を含む、関数の出力が表示されます。

------
#### [ CLI ]

**aws cloudfront test-function** コマンドを使用して関数をテストできます。

**関数をテストするには**

1. コマンドラインウィンドウを開きます。

1. 指定したファイルがある同じディレクトリから、次のコマンドを実行します。

   この例では、`fileb://` 表記を使用してイベントオブジェクトファイルを渡します。コマンドを読みやすくするために改行も含まれています。

   ```
   aws cloudfront test-function \
       --name MaxAge \
       --if-match ETVABCEXAMPLE \
       --event-object fileb://event-maxage-test01.json \
       --stage DEVELOPMENT
   ```
**注意事項**  
関数は名前と ETag (`if-match` パラメータ内) で参照します。イベントオブジェクトはファイルシステム内のロケーションによって参照します。
ステージは、`DEVELOPMENT` または `LIVE` の場合があります。

   コマンドが成功した場合は、以下のような出力が表示されます。

   ```
   TestResult:
     ComputeUtilization: '21'
     FunctionErrorMessage: ''
     FunctionExecutionLogs: []
     FunctionOutput: '{"response":{"headers":{"cloudfront-functions":{"value":"generated-by-CloudFront-Functions"},"location":{"value":"https://aws.amazon.com/cloudfront/"}},"statusDescription":"Found","cookies":{},"statusCode":302}}'
     FunctionSummary:
       FunctionConfig:
         Comment: MaxAge function
         Runtime: cloudfront-js-2.0
         KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
       FunctionMetadata:
         CreatedTime: '2021-04-18T20:38:56.915000+00:00'
         FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge
         LastModifiedTime: '2023-17-20T10:38:57.057000+00:00'
         Stage: DEVELOPMENT
       Name: MaxAge
       Status: UNPUBLISHED
   ```

------

**注意事項**  
`FunctionExecutionLogs` には、関数が `console.log()` ステートメントに書き込んだ (該当する場合) ログ行のリストが含まれます。
`ComputeUtilization` には、関数の実行に関する情報が含まれています。「[コンピューティング使用率を理解する](#compute-utilization)」を参照してください。
`FunctionOutput` には、関数が返したイベントオブジェクトが含まれます。

## コンピューティング使用率を理解する
<a name="compute-utilization"></a>

**コンピューティング使用率**は、関数の実行にかかった時間 (最大許容時間に対するパーセンテージ) です。たとえば、値 35 は、関数が最大許容時間の 35% で完了したことを意味します。

関数が最大許容時間を継続的に超える場合、CloudFront で関数がスロットリングされます。次のリストは、コンピューティング使用率の値に基づいて関数がスロットリングされる可能性を説明しています。

**コンピューティング使用率値:**
+ ** 1～50** —関数は最大許容時間を十分に下回っており、スロットリングなしで実行する必要があります。
+ ** 51～70** —関数が最大許容時間に近づいています。関数コードの最適化を検討してください。
+ ** 71～100** —関数が最大許容時間に非常に近いか、それを超えています。ディストリビューションに関連付けると、CloudFront でこの関数が抑制される可能性があります。

# 関数を更新する
<a name="update-function"></a>

関数はいつでも更新できます。変更は、`DEVELOPMENT` ステージ内の関数のバージョンに対してのみ行われます。更新を `DEVELOPMENT` ステージから `LIVE` にコピーするには、[関数を発行](publish-function.md)する必要があります。

関数のコードを更新するには、CloudFront コンソールまたは AWS Command Line Interface (AWS CLI) を使用できます。

------
#### [ Console ]

**関数コードを更新するには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

   対象の関数を選択します。

1. **[編集]** を選択し、以下の変更を行います。
   + **[詳細]** セクションのフィールドを更新します。
   + 関連するキー値ストアを変更または削除します。キー値ストアの詳細については、「[Amazon CloudFront KeyValueStore](kvs-with-functions.md)」を参照してください。
   + 関数コードを変更します。**[ビルド]** タブを選択し、変更を加え、**[変更を保存]** を選択してコードへの変更を保存します。

------
#### [ CLI ]

**関数コードを更新するには**

1. コマンドラインウィンドウを開きます。

1. 以下のコマンドを実行してください。

   この例では、`fileb://` 表記を使用してファイルを渡します。コマンドを読みやすくするために改行も含まれています。

   ```
   aws cloudfront update-function \
       --name MaxAge \
       --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"}]}}' \
       --function-code fileb://function-max-age-v1.js \
       --if-match ETVABCEXAMPLE
   ```
**注意事項**  
関数は名前と ETag (`if-match` パラメータ内) の両方で識別できます。必ず現在の ETag を使用してください。[DescribeFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeFunction.html) API オペレーションを使用してこの値を取得できます。
変更したくない場合でも、`function-code` を含める必要があります。
`function-config` には注意してください。設定に保持するすべてのものを渡す必要があります。具体的には、キー値ストアを次のように処理してください。  
既存のキー値ストアの関連付け (存在する場合) を維持するには、既存のストアの名前を指定します。**
関連付けを変更するには、新しいキー値ストアの名前を指定します。**
関連付けを削除するには、`KeyValueStoreAssociations` パラメータを省略します。

   コマンドが成功した場合は、以下のような出力が表示されます。

   ```
   ETag: ETVXYZEXAMPLE
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years \
       Runtime: cloudfront-js-2.0 \
       KeyValueStoreAssociations= \
         {Quantity=1, \
         Items=[{KeyValueStoreARN='arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111'}]} \
     FunctionMetadata: \
       CreatedTime: '2021-04-18T20:38:56.915000+00:00' \
       FunctionARN: arn:aws:cloudfront::111122223333:function/MaxAge \
       LastModifiedTime: '2023-12-19T23:41:15.389000+00:00' \
       Stage: DEVELOPMENT \
     Name: MaxAge \
     Status: UNPUBLISHED
   ```

------

ほとんどの情報はリクエストから繰り返されます。その他の情報は CloudFront によって追加されます。

**注意事項**  
`ETag` – この値は、キー値ストアを変更するたびに変わります。
`FunctionARN` – CloudFront 関数の ARN。
`Stage` – 関数のステージ (`LIVE` または `DEVELOPMENT`）。
`Status` – 関数のステータス (`PUBLISHED` または `UNPUBLISHED`)。

# 関数を発行する
<a name="publish-function"></a>

関数を発行すると、関数が `DEVELOPMENT` ステージから `LIVE` ステージにコピーされます。

キャッシュ動作が関連付けられていない関数を発行した場合は、関数をキャッシュ動作に関連付けることができます。キャッシュ動作は、`LIVE` ステージの関数にのみ関連付けることができます。

**重要**  
関数を発行する前に、[テスト](test-function.md)することをお勧めします。
関数を発行すると、関数に関連付けられたすべてのキャッシュ動作は (ディストリビューションのデプロイが完了しだい)、新しく発行したコピーを自動的に使用するようになります。

CloudFront コンソールまたは AWS CLI を使用して、関数を公開できます。

------
#### [ Console ]

**関数を発行するには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

1. 対象の関数を選択します。

1. **[発行]** タブを選択し、**[発行]** を選択します。関数が 1 つ以上のキャッシュ動作に既にアタッチされている場合は、**[発行して更新]** を選択します。

1. (オプション) 関数に関連付けられたディストリビューションを表示するには、[**Associated CloudFront distributions**] を選択して、そのセクションを展開します。

正常に完了すると、ページの上部に「***関数名*は正常に発行されました**」というバナーが表示されます。[**Build**] タブから [**Live**] を選択して、関数コードのライブバージョンを表示することもできます。

------
#### [ CLI ]

**関数を発行するには**

1. コマンドラインウィンドウを開きます。

1. 次の **aws cloudfront publish-function** コマンドを実行します。この例では、例を読みやすくするために改行されています。

   ```
   aws cloudfront publish-function \
       --name MaxAge \
       --if-match ETVXYZEXAMPLE
   ```

   コマンドが成功した場合は、以下のような出力が表示されます。

   ```
   FunctionSummary:
     FunctionConfig:
       Comment: Max Age 2 years
       Runtime: cloudfront-js-2.0
     FunctionMetadata:
       CreatedTime: '2021-04-18T21:24:21.314000+00:00'
       FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
       LastModifiedTime: '2023-12-19T23:41:15.389000+00:00'
       Stage: LIVE
     Name: MaxAge
     Status: UNASSOCIATED
   ```

------

# 関数をディストリビューションに関連付ける
<a name="associate-function"></a>

ディストリビューションで関数を使用するには、関数をディストリビューションの 1 つ以上のキャッシュ動作に関連付けます。関数を複数のディストリビューションの複数のキャッシュ動作に関連付けることができます。

関数は以下のいずれかに関連付けることができます。
+ 既存のキャッシュ動作
+ 既存のディストリビューションの新しいキャッシュ動作
+ 新しいディストリビューションの新しいキャッシュ動作

関数をキャッシュ動作に関連付ける場合は、*イベントタイプ*を選択する必要があります。CloudFront がいつ関数を実行するかは、イベントタイプで決まります。

次のイベントタイプを選択できます。
+ **ビューワーリクエスト** - CloudFront がビューワーからリクエストを受信するとこの関数が実行されます。
+ **ビューワーレスポンス** - CloudFront がビューワーにレスポンスを返す前にこの関数が実行されます。

CloudFront Functions では、オリジン向けのイベントタイプ (オリジンリクエストとオリジンレスポンス) を使用することはできません。****代わりに Lambda@Edge を使用できます。詳細については、「[Lambda@Edge 関数をトリガーできる CloudFront イベント](lambda-cloudfront-trigger-events.md)」を参照してください。

**注記**  
関数を関連付ける前に、[その関数をステージ `LIVE` に公開](publish-function.md)する必要があります。

関数をディストリビューションに関連付けるには、CloudFront コンソールまたは AWS Command Line Interface (AWS CLI) を使用できます。次の手順は、関数を既存のキャッシュ動作に関連付ける方法を示しています。

------
#### [ Console ]

**関数を既存のキャッシュ動作に関連付けるには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

1. 関連付ける関数を選択します。

1. **[関数]** ページで、**[発行]** タブを選択します。

1. **[関数を発行]** を選択します。

1. [**Add association**] を選択します。表示されるダイアログで、ディストリビューション、イベントタイプ、および/またはキャッシュ動作を選択します。

   イベントタイプでは、この関数を実行するタイミングを選択します。
   + **ビューワーリクエスト** – CloudFront がリクエストを受信するたびに関数を実行します。
   + **ビューワーレスポンス** – CloudFront がレスポンスを返すたびに関数を実行します。

1. 設定を保存するには、**[関連付けを追加]** を選択します。

CloudFront は関数に ディストリビューションを関連付けます。関連付けられたディストリビューションのデプロイが完了するまで数分待ちます。関数の詳細ページで **[ディストリビューションを表示]** を選択すると、進行状況を確認できます。

------
#### [ CLI ]

**関数を既存のキャッシュ動作に関連付けるには**

1. コマンドラインウィンドウを開きます。

1. 次のコードを使用して、関数に関連付けるキャッシュ動作を持つディストリビューションのディストリビューション設定を保存します。このコマンドは、ディストリビューション設定を `dist-config.yaml` という名前のファイルに保存します。このコマンドを使用するには、次の操作を行います。
   + *`DistributionID`* をディストリビューションの ID に置き換えます。
   + コマンドを 1 行で実行します。この例では、例を読みやすくするために改行されています。

   ```
   aws cloudfront get-distribution-config \
       --id DistributionID \
       --output yaml > dist-config.yaml
   ```

   コマンドが正常に完了した場合、AWS CLI は出力を返しません。

1. 作成した `dist-config.yaml` という名前のファイルを開きます。ファイルを編集して以下の変更を加えます。

   1. `ETag` フィールドの名前を `IfMatch` に変更しますが、フィールドの値は変更しないでください。

   1. キャッシュ動作で、`FunctionAssociations` という名前のオブジェクトを見つけます。このオブジェクトを更新して、関数の関連付けを追加します。関数を関連付ける YAML 構文は、次の例のようになります。
      + 次の例は、ビューワーリクエストイベントタイプ (トリガー) を示しています。ビューアレスポンスイベントタイプを使用するには、`viewer-request` を `viewer-response` に置き換えます。
      + *`arn:aws:cloudfront::111122223333:function/ExampleFunction`* は、このキャッシュ動作に関連付ける関数の Amazon リソースネーム (ARN) に置き換えます。関数 ARN を取得するには、**aws cloudfront list-functions** コマンドを使用します。

      ```
      FunctionAssociations:
        Items:
          - EventType: viewer-request
            FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
        Quantity: 1
      ```

   1. 変更が完了したら、ファイルを保存します。

1. 関数の関連付けを追加してディストリビューションを更新するには、次のコマンドを使用します。このコマンドを使用するには、次の操作を行います。
   + *`DistributionID`* をディストリビューションの ID に置き換えます。
   + コマンドを 1 行で実行します。この例では、例を読みやすくするために改行されています。

   ```
   aws cloudfront update-distribution \
       --id DistributionID \
       --cli-input-yaml file://dist-config.yaml
   ```

   コマンドが正常に完了すると、関数の関連付けで更新されたばかりのディストリビューションを説明する次のような出力が表示されます。次の出力例は、読みやすくするために切り詰めています。

   ```
   Distribution:
     ARN: arn:aws:cloudfront::111122223333:distribution/EBEDLT3BGRBBW
     ... truncated ...
     DistributionConfig:
       ... truncated ...
       DefaultCacheBehavior:
         ... truncated ...
         FunctionAssociations:
           Items:
           - EventType: viewer-request
             FunctionARN: arn:aws:cloudfront::111122223333:function/ExampleFunction
           Quantity: 1
         ... truncated ...
     DomainName: d111111abcdef8.cloudfront.net
     Id: EDFDVBD6EXAMPLE
     LastModifiedTime: '2021-04-19T22:39:09.158000+00:00'
     Status: InProgress
   ETag: E2VJGGQEG1JT8S
   ```

------

ディストリビューションが再デプロイされる間に、ディストリビューションの `Status` は `InProgress` に変更されます。新しいディストリビューション設定が CloudFront エッジロケーションに到達すると、エッジロケーションは関連する関数の使用を開始します。ディストリビューションのデプロイが完了すると、`Status` は `Deployed` に戻ります。これは、関連する CloudFront 関数が世界中のすべての CloudFront エッジロケーションで稼働していることを示します。これには通常数分かかります。

# Amazon CloudFront KeyValueStore
<a name="kvs-with-functions"></a>

CloudFront KeyValueStore は、[CloudFront Functions](cloudfront-functions.md) 内からの読み取りアクセスを許可する、安全でグローバルな低レイテンシーのキー値データストアであり、CloudFront エッジロケーションで高度かつカスタマイズ可能なロジックを利用できるようにします。

CloudFront KeyValueStore では、関数コードを更新したり、関数に関連付けられているデータを個別に更新できます。このように分離することで関数コードが簡略化され、コードの変更をデプロイしなくてもデータを簡単に更新できます。

**注記**  
CloudFront KeyValueStore を使用するには、CloudFront 関数で [JavaScript ランタイム 2.0](functions-javascript-runtime-20.md) を使用する必要があります。

キーと値のペアを使用するための一般的な手順は、次のとおりです。
+ キーバリューストアを作成して、このストア内に一連のキーと値のペアを設定します。キーバリューストアは、Amazon S3 バケットに追加することも、手動で入力することもできます。
+ キーバリューストアを CloudFront 関数に関連付けます。
+ 関数コード内で、キーの名前を使用してキーに関連付けられた値を取得するか、キーの存在を評価します。キーと値のペアを関数コードで使用する方法と、ヘルパーメソッドの詳細については、「[キーバリューストアのヘルパーメソッド](functions-custom-methods.md)」を参照してください。

## ユースケース
<a name="key-value-store-use-cases"></a>

キーと値のペアは、以下の例に示すように使用できます。
+ **URL の書き換えまたはリダイレクト** — キーと値のペアは、書き換えられた URL またはリダイレクト URL を保持できます。
+ **A/B テストと機能フラグ** – ウェブサイトの特定のバージョンにトラフィックの割合を割り当てることで、テストを実行する関数を作成できます。
+ **アクセスの認可** – 独自に定義した条件とキーバリューストアに保存したデータに基づいて、リクエストを許可または拒否するアクセスコントロールを実装できます。

## サポートされている値の形式
<a name="key-value-store-supported-formats"></a>

キーと値のペアの値は、以下のいずれかの形式で保存できます。
+ String
+ バイトでエンコードされた文字列
+ JSON 

## セキュリティ
<a name="key-value-store-security"></a>

CloudFront 関数およびすべてのキーバリューストアのデータは、次のように安全に処理されます。
+ [CloudFront KeyValueStore](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_Operations_Amazon_CloudFront_KeyValueStore.html) API オペレーションを呼び出すと、CloudFront は保管中および転送中の各キーバリューストアを (読み取り時または書き込み時に) 暗号化します。
+ 関数を実行すると、CloudFront は CloudFront エッジロケーションでメモリ内のキーと値の各ペアを復号します。

CloudFront KeyValueStore の使用を開始するには、以下のトピックを参照してください。

**Topics**
+ [ユースケース](#key-value-store-use-cases)
+ [サポートされている値の形式](#key-value-store-supported-formats)
+ [セキュリティ](#key-value-store-security)
+ [キーバリューストアの操作](kvs-with-functions-kvs.md)
+ [キーと値のデータを操作する](kvs-with-functions-kvp.md)
+ CloudFront KeyValueStore の使用を開始する方法の詳細については、AWS ブログ記事「[Amazon CloudFront KeyValueStore の紹介](https://aws.amazon.com/blogs/aws/introducing-amazon-cloudfront-keyvaluestore-a-low-latency-datastore-for-cloudfront-functions/)」を参照してください。

# キーバリューストアの操作
<a name="kvs-with-functions-kvs"></a>

CloudFront Functions で使用するキーと値のペアを保持するには、キーバリューストアを作成する必要があります。

キーバリューストアを作成してキーと値のペアを追加すると、CloudFront 関数コードでキー値を使用できます。

最初に、以下のトピックを参照してください。

**Topics**
+ [キーバリューストアの作成](kvs-with-functions-create.md)
+ [キーバリューストアを関数に関連付ける](kvs-with-functions-associate.md)
+ [キーバリューストアを更新する](kvs-with-functions-edit.md)
+ [キー値ストアへの参照の取得](kvs-with-functions-get-reference.md)
+ [キーバリューストアの削除](kvs-with-functions-delete.md)
+ [キーと値のペアのファイル形式](kvs-with-functions-create-s3-kvp.md)

**注記**  
JavaScript ランタイム 2.0 には、関数コード内のキー値を操作するためのヘルパーメソッドがいくつか含まれています。詳細については、「[キーバリューストアのヘルパーメソッド](functions-custom-methods.md)」を参照してください。

# キーバリューストアの作成
<a name="kvs-with-functions-create"></a>



キーバリューストアおよびキーと値のペアを同時に作成できます。最初に空のキーバリューストアを作成し、後でキーと値のペアを追加することもできます。

**注記**  
Amazon S3 バケット内のデータソースを指定する場合は、そのバケットに対する `s3:GetObject` と `s3:GetBucketLocation` のアクセス許可が必要です。これらのアクセス許可がない場合、CloudFront はキーバリューストアを正常に作成できません。

キーバリューストアを作成すると同時にキーと値のペアを追加するかどうかを決定します。key-value ペアは、CloudFront コンソール、CloudFront API、AWS SDK を使用してインポートできます。ただし、key-value ペアのファイルをインポートできるのは、最初にキーバリューストアを作成する際にのみです。**

key-value ペアのファイルを作成するには、「[キーと値のペアのファイル形式](kvs-with-functions-create-s3-kvp.md)」を参照してください。

------
#### [ Console ]

**キーバリューストアを作成するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) で CloudFront コンソールの **[関数]** ページを開きます。

1. **[KeyValueStores]** タブを選択し、**[KeyValueStore を作成]** を選択します。

1. キーバリューストアの名前とオプションで説明を入力します。

1. **[S3 URI]** を入力します。
   + キーと値のペアのファイルを持っている場合は、ファイルを保存した Amazon S3 バケットへのパスを入力します。
   + キーと値のペアを手動で入力する場合は、このフィールドを空白のままにします。

1. **[作成]** を選択します。これで、キーバリューストアが作成されました。

   新しいキーバリューストアの詳細ページが表示されます。ページの情報には、キーバリューストアの ID と ARN が含まれます。
   + ID は、AWS アカウント内で固有のランダムな文字列です。
   + ARN の構文は次のとおりです。

     *AWS アカウント*`:key-value-store/`*キーバリューストア ID*

1. **[キーと値のペア]** セクションを見てください。ファイルをインポートした場合、このセクションには、いくつかのキーと値のペアが表示されます。以下の操作を行うことができます。
   + ファイルをインポートした場合は、他の値を手動で追加することもできます。
   + Amazon S3 バケットからファイルをインポートしていない場合、ここでキーと値のペアを追加するには、次のステップを実行できます。
   + このステップをスキップして、後でキーと値のペアを追加できます。

1. ここでペアを追加するには:

   1. **[キーと値のペアを追加]** を選択します。

   1. **[ペアの追加]** ボタンを選択して名前と値を入力します。さらにペアを追加するには、このステップを繰り返します。

   1. 完了したら、**[変更を保存]** を選択してキーバリューストアにすべてのキーと値のペアを保存します。表示されたダイアログボックスで **[完了]** を選択します。

1. 今すぐキーバリューストアを関数に関連付ける場合は、**[関連付けられている関数]** セクションに入力します。詳細については「[関数を作成する](create-function.md)」または「[関数を更新する](update-function.md)」を参照してください。

   関数の関連付けは、後で、このキーバリューストアの詳細ページまたは関数の詳細ページから行うこともできます。

------
#### [ AWS CLI ]

**キーバリューストアを作成するには**
+ 次のコマンドを実行して、キーバリューストアを作成し、Amazon S3 バケットから key-value ペアをインポートします。

  ```
  aws cloudfront create-key-value-store \
      --name=keyvaluestore1 \
      --comment="This is my key value store file" \
      --import-source=SourceType=S3,SourceARN=arn:aws:s3:::amzn-s3-demo-bucket1/kvs-input.json
  ```

  **応答**

  ```
  {
      "ETag": "ETVABCEXAMPLE",
      "Location": "https://cloudfront.amazonaws.com/2020-05-31/key-value-store/arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
      "KeyValueStore": {
          "Name": "keyvaluestore1",
          "Id": "8aa76c93-3198-462c-aaf6-example",
          "Comment": "This is my key value store file",
          "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
          "Status": "PROVISIONING",
          "LastModifiedTime": "2024-08-06T22:19:10.813000+00:00"
      }
  }
  ```

------
#### [ API ]

**キーバリューストアを作成するには**

1. [CloudFront CreateKeyValueStore](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_CreateKeyValueStore.html) オペレーションを使用します。このオペレーションには複数のパラメータが必要です。
   + キーバリューストアの `name`
   + コメントを含む `comment` パラメータ。
   + Amazon S3 バケットに保存したファイルからキーと値のペアをインポートするための `import-source` パラメータ。ファイルからインポートできるのは、最初にキーバリューストアを作成する際のみです。ファイルの構造については、「[キーと値のペアのファイル形式](kvs-with-functions-create-s3-kvp.md)」を参照してください。

オペレーションレスポンスには、以下の情報が含まれます。
+ リクエストで渡された値 (割り当てた名前を含む)。
+ 作成時間などのデータ。
+ `ETag` (`ETVABCEXAMPLE` など)、キーバリューストア名を含む ARN (`arn:aws:cloudfront::123456789012:key-value-store/keyvaluestore1` など) 

  キーバリューストアをプログラムで操作するには、`ETag`、ARN、名前の組み合わせを使用します。

------

## キーバリューストアのステータス
<a name="key-value-store-status"></a>

キーバリューストアを作成する場合、データストアのステータス値は次のようになります。


****  

| 値 | 説明 | 
| --- | --- | 
|  **プロビジョニング**  |  キーバリューストアが作成済みであり、指定したデータソースを CloudFront が処理中です。  | 
|  **Ready**  |  キーバリューストアが作成済みであり、指定したデータソースを CloudFront が正常に処理しました。  | 
|  **インポート失敗**  |  CloudFront は、指定したデータソースを処理できませんでした。このステータスは、ファイルの形式が有効でないか、ファイルのサイズが制限を超えている場合に表示されることがあります。詳細については、「[キーと値のペアのファイル形式](kvs-with-functions-create-s3-kvp.md)」を参照してください。  | 

# キーバリューストアを関数に関連付ける
<a name="kvs-with-functions-associate"></a>

キーバリューストアを作成したら、関数を更新してキーバリューストアに関連付けることができます。この関連付けは、キーバリューストア内のキーと値のペアを、関数で使用するために必要です。以下のルールが適用されます。
+ 1 つの関数には 1 つのキーバリューストアのみを関連付けることができます。
+ 同じキーバリューストアを複数の関数に関連付けることができます。

------
#### [ Console ]

**キーバリューストアを関数に関連付けるには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions)) にサインインし、**[関数]** ページを選択します。

1. 関数名を選択します。

1. **[KeyValueStore を関連付け]** セクションに移動して、**[既存の KeyValueStore を関連付け]** を選択します。

1. 関数のキーと値のペアを含むキーバリューストアを選択し、**[KeyValueStore を関連付ける]** を選択します。

   CloudFront はストアを直ちに関数に関連付けます。関数を保存する必要はありません。

1. 別のキーバリューストアを指定するには、**[関連付けられた KeyValueStore を更新]** を選択し、別のキーバリューストア名を選択してから、**[KeyValueStore を関連付ける]** を選択します。

詳細については、「[関数を更新する](update-function.md)」を参照してください。

------
#### [ AWS CLI ]

**キーバリューストアを関数に関連付けるには**
+ `MaxAge` 関数を更新し、キーバリューストアのリソースを関連付けるには、次のコマンドを実行します。

  ```
  aws cloudfront update-function \
      --name MaxAge \
      --function-config '{"Comment":"Max Age 2 years","Runtime":"cloudfront-js-2.0","KeyValueStoreAssociations":{"Quantity":1,"Items":[{"KeyValueStoreARN":"arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example"}]}}' \
      --function-code fileb://function-max-age-v1.js \
      --if-match ETVABCEXAMPLE
  ```
+ キーバリューストアを関数に関連付けるには、`KeyValueStoreAssociations` パラメータとキーバリューストア ARN を指定します。
+ 関連付けを変更するには、別のキーバリューストア ARN を指定します。
+ 関連付けを削除するには、`KeyValueStoreAssociations` パラメータを消去します。

詳細については、「[関数を更新する](update-function.md)」を参照してください。

------
#### [ API ]

**キーバリューストアを関数に関連付けるには**
+ [UpdateFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateFunction.html) API オペレーションを使用します。詳細については、「[関数を更新する](update-function.md)」を参照してください。

------

**注意事項**  
キーと値のペアを変更せずにキーバリューストアを変更した場合や、キーバリューストア内のキーと値のペアのみを変更した場合は、キーバリューストアを再度関連付ける必要はありません。また、関数を再発行する必要もありません。  
ただし、関数をテストして、正常に動作することを確認することをお勧めします。詳細については、「[関数をテストする](test-function.md)」を参照してください。
特定のキーバリューストアを使用するすべての関数を表示できます。CloudFront コンソールで、キーバリューストアの詳細ページを選択します。

# キーバリューストアを更新する
<a name="kvs-with-functions-edit"></a>

キーバリューストアを更新するときに、キーと値のペアを変更したり、キーバリューストアと関数の関連付けを変更したりできます。

------
#### [ Console ]

**キーバリューストアを更新するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) で CloudFront コンソールの **[関数]** ページを開きます。

1. **[KeyValueStores]** タブを選択します。

1.  更新するキーバリューストアを選択します。
   + キーと値のペアを更新するには、**[キーと値のペア]** セクションで **[編集]** を選択します。任意の数のキーと値のペアを追加または削除できます。また、既存のキーと値のペアの値を変更することもできます。完了したら、[**変更の保存**] を選択します。
   + このキーバリューストアの関連付けを更新するには、**[関数へ移動]** を選択します。詳細については、「[キーバリューストアを関数に関連付ける](kvs-with-functions-associate.md)」を参照してください。

------
#### [ AWS CLI ]

**キーバリューストアを更新するには**

1. **key-value ペアの変更** – key-value ペアを追加したり、単一または複数の key-value ペアを削除したり、既存の key-value ペアの値を変更したりできます。詳細については、「[キーと値のデータを操作する](kvs-with-functions-kvp.md)」を参照してください。

1. **キーバリューストアの関数の関連付けの変更** – キーバリューストアの関連付けを更新するには、「[キーバリューストアを関数に関連付ける](kvs-with-functions-associate.md)」を参照してください。
**ヒント**  
キーバリューストアの ARN が必要になります。詳細については、「[キー値ストアへの参照の取得](kvs-with-functions-get-reference.md)」を参照してください。

------
#### [ API ]

**キーバリューストアを更新するには**

1. **key-value ペアの変更** – key-value ペアを追加したり、単一または複数の key-value ペアを削除したり、既存の key-value ペアの値を変更したりできます。詳細については、「[キーと値のデータを操作する](kvs-with-functions-kvp.md)」を参照してください。

1. **キーバリューストアの関数の関連付けの変更** – キーバリューストアの関連付けを更新するには、[UpdateFunction](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateFunction.html) API オペレーションを使用します。詳細については、「[関数を更新する](update-function.md)」を参照してください。
**ヒント**  
キーバリューストアの ARN が必要になります。詳細については、「[キー値ストアへの参照の取得](kvs-with-functions-get-reference.md)」を参照してください。

------

# キー値ストアへの参照の取得
<a name="kvs-with-functions-get-reference"></a>

キーバリューストアをプログラムで操作するには、キーバリューストアの `ETag` と名前が必要です。

両方の値を取得するには、AWS Command Line Interface (AWS CLI) または CloudFront API を使用できます。

------
#### [ AWS CLI ]

**キーバリューストアへの参照を取得するには**

1. キーバリューストアのリストを返すには、次のコマンドを実行します。変更するキーバリューストア名を検索します。

   ```
   aws cloudfront list-key-value-stores
   ```

1. 応答から変更するキーバリューストア名を検索します。

   **応答**

   ```
   {
       "KeyValueStoreList": {
           "Items": [
               {
                   "Name": "keyvaluestore3",
                   "Id": "37435e19-c205-4271-9e5c-example3",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example3",
                   "Status": "READY",
                   "LastModifiedTime": "2024-05-08T14:50:18.876000+00:00"
               },
               {
                   "Name": "keyvaluestore2",
                   "Id": "47970d59-6408-474d-b850-example2",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/47970d59-6408-474d-b850-example2",
                   "Status": "READY",
                   "LastModifiedTime": "2024-05-30T21:06:22.113000+00:00"
               },
               {
                   "Name": "keyvaluestore1",
                   "Id": "8aa76c93-3198-462c-aaf6-example",
                   "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
                   "Status": "READY",
                   "LastModifiedTime": "2024-08-06T22:19:30.510000+00:00"
               }
           ]
       }
   }
   ```

1. 特定のキーバリューストアの `ETag` を返すには、次のコマンドを実行します。

   ```
   aws cloudfront describe-key-value-store \
       --name=keyvaluestore1
   ```

   **応答**

   ```
   {
       "ETag": "E3UN6WX5RRO2AG",
       "KeyValueStore": {
           "Name": "keyvaluestore1",
           "Id": "8aa76c93-3198-462c-aaf6-example",
           "Comment": "This is an example KVS",
           "ARN": "arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example",
           "Status": "READY",
           "LastModifiedTime": "2024-08-06T22:19:30.510000+00:00"
       }
   }
   ```

------
#### [ API ]

**キーバリューストアへの参照を取得するには**

1. [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html) API オペレーションを使用して、キーバリューストアのリストを返します。変更するキーバリューストアの名前を探します。

1. [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DescribeKeyValueStore.html) API オペレーションを使用して、前のステップで返したキーバリューストアの名前を指定します。

------

この応答には、UUID、キーバリューストアの ARN、キーバリューストアの `ETag` が含まれます。
+ `E3UN6WX5RRO2AG` などの `ETag`
+ UUID は `8aa76c93-3198-462c-aaf6-example` などの 128 ビットです。
+ ARN には、次の例に示すように AWS アカウント 番号、定数 `key-value-store`、UUID が含まれます。

  `arn:aws:cloudfront::123456789012:key-value-store/8aa76c93-3198-462c-aaf6-example`

`DescribeKeyValueStore` 操作の詳細については、「[CloudFront KeyValueStore について](kvs-with-functions-kvp.md#kvs-with-functions-api-describe)」を参照してください。

# キーバリューストアの削除
<a name="kvs-with-functions-delete"></a>

キーバリューストアを削除するには、Amazon CloudFront コンソールまたは API を使用できます。

------
#### [ Console ]

**キーバリューストアを削除するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) で CloudFront コンソールの **[関数]** ページを開きます。

1. 関数名を選択します。

1. **[関連付けられた KeyValueStore]** セクションで、キーバリューストアが関数に関連付けられているかどうかを確認します。関連付けられている場合は、**[KeyValueStore の関連付けを解除]** を選択し、**[関連付けの削除]** を選択します。

1. ナビゲーションペインで、**[関数]** ページ、**[KeyValueStores]** タブの順に選択します。

1. 削除するキーバリューストアを選択し、**[削除]** を選択します。

------
#### [ AWS CLI ]

**キーバリューストアを削除するには**

1. キーバリューストアの `ETag` と名前を取得します。詳細については、「[キー値ストアへの参照の取得](kvs-with-functions-get-reference.md)」を参照してください。

1. キーバリューストアが関数に関連付けられているかどうかを確認します。関連付けられている場合は､それを削除します｡ これらの両方のステップの詳細については、「[関数を更新する](update-function.md)」を参照してください。

1. キーバリューストアの名前と `ETag` を取得して、関数との関連付けがなくなったら、削除できます。

   特定のキーバリューストアを削除するには、次のコマンドを実行します。

   ```
   aws cloudfront delete-key-value-store \
       --name=keyvaluestore1 \
       --if-match=E3UN6WX5RRO2AG
   ```

------
#### [ API ]

**キーバリューストアを削除するには**

1. キーバリューストアの `ETag` と名前を取得します。詳細については、「[キー値ストアへの参照の取得](kvs-with-functions-get-reference.md)」を参照してください。

1. キーバリューストアが関数に関連付けられているかどうかを確認します。関連付けられている場合は､それを削除します｡ これらの両方のステップの詳細については、「[関数を更新する](update-function.md)」を参照してください。

1. キーバリューストアを削除するには、CloudFront の [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DeleteKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_DeleteKeyValueStore.html) API オペレーションを使用します。

------

# キーと値のペアのファイル形式
<a name="kvs-with-functions-create-s3-kvp"></a>

UTF-8 でエンコードしたファイルを作成するときは、次の JSON 形式を使用します。

```
{
  "data":[
    {
      "key":"key1",
      "value":"value"
    },
    {
      "key":"key2",
      "value":"value"
    }
  ]
}
```

ファイルに重複キーを含めることはできません。Amazon S3 バケットに無効なファイルを指定した場合は、ファイルを更新して重複を削除してから、キーバリューストアを作成し直してみてください。

詳細については、「[キーバリューストアの作成](kvs-with-functions-create.md)」を参照してください。

**注記**  
データソースのファイルとそのキーと値のペアには、以下の制限があります。  
ファイルサイズ — 5 MB
キーサイズ — 512 文字
値のサイズ — 1024 文字

# キーと値のデータを操作する
<a name="kvs-with-functions-kvp"></a>

このトピックでは、既存のキーバリューストアにキーと値のペアを追加する方法について説明します。キーバリューストアを最初に作成するときに、キーと値のペアを含めるには、「[キーバリューストアの作成](kvs-with-functions-create.md)」を参照してください。

**Topics**
+ [key-value ペアを使用する (コンソール)](#kvs-with-functions-kvp-using-console)
+ [CloudFront KeyValueStore について](#kvs-with-functions-api-describe)
+ [key-value ペアを使用する (AWS CLI)](#work-with-kvs-cli-keys)
+ [key-value ペアを使用する (API)](#kvs-with-functions-kvp-using-api)

## key-value ペアを使用する (コンソール)
<a name="kvs-with-functions-kvp-using-console"></a>

CloudFront コンソールを使用してキーと値のペアを操作できます。

**キーと値のペアを使用するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home#/functions](https://console.aws.amazon.com/cloudfront/v4/home#/functions) で CloudFront コンソールの **[関数]** ページを開きます。

1. **[KeyValueStores]** タブを選択します。

1. 変更するキーバリューストアを選択します。

1. **[キーと値のペア]** セクションで、**[編集]** を選択します。

1. キーと値のペアを追加または削除したり、既存のキーと値のペアの値を変更したりできます。

1. 完了したら、[**変更の保存**] を選択します。

## CloudFront KeyValueStore について
<a name="kvs-with-functions-api-describe"></a>

**ヒント**  
CloudFront KeyValueStore API は、認証に Signature Version 4A (SigV4A) を使用するグローバルサービスです。SigV4A で一時的な認証情報を使用するには、Version 2 のセッショントークンが必要です。詳細については、「[CloudFront KeyValueStore API での一時的な認証情報の使用](cloudfront-function-restrictions.md#regional-endpoint-for-key-value-store)」を参照してください。

AWS Command Line Interface (AWS CLI) または独自のコードを使用して CloudFront KeyValueStore API を呼び出す場合は、以降のセクションを参照してください。

キーバリューストアとそのキーと値のペアを操作する場合、呼び出すサービスはユースケースによって異なります。
+ 既存のキーバリューストア内の key-value ペアをプログラムで操作するには、CloudFront KeyValueStore サービスを使用します。**
+ キーバリューストアを最初に作成するときに、キーバリューストアにキーと値のペアを含めるには、CloudFront サービスを使用します。**

CloudFront API と CloudFront KeyValueStore API の両方に `DescribeKeyValueStore` オペレーションがあります。さまざまな理由でこれらを呼び出すことができます。違いを理解するには、次の表を参照してください。


|  | CloudFront DescribeKeyValueStore API | CloudFront KeyValueStore DescribeKeyValueStore API | 
| --- | --- | --- | 
| キーバリューストアに関するデータ |  キーバリューストア自体の最終変更時のステータスや日付などのデータを返します。  |  ストレージリソースのコンテンツに関するデータ (ストア内のキーと値のペア、コンテンツのサイズ) を返します。**  | 
| キーバリューストアを識別するデータ |  キーバリューストアの `ETag`、UUID、ARN を返します。  |  キーバリューストアの `ETag` と ARN を返します。  | 

**注意事項**  
各 DescribeKeyValueStore オペレーションは、別々の `ETag` を返します。**`ETags` は置き換え可能ではありません。
API オペレーションを呼び出してアクションを実行する際は、適切な API から `ETag` を指定する必要があります。例えば、CloudFront KeyValueStore の [ DeleteKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DeleteKey.html) オペレーションでは、CloudFront KeyValueStore [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html) オペレーションから返された `ETag` を指定します。
CloudFront KeyValueStore を使用して CloudFront Functions を呼び出す場合、キーバリューストアの値は関数の呼び出し中に更新または変更されません。更新は、関数の呼び出しの合間に処理されます。

## key-value ペアを使用する (AWS CLI)
<a name="work-with-kvs-cli-keys"></a>

CloudFront KeyValueStore に関しては、以下の AWS Command Line Interface コマンドを実行できます。

**Contents**
+ [key-value ペアの一覧表示](#kvs-cli-list-keys)
+ [key-value ペアの取得](#kvs-cli-get-keys)
+ [キーバリューストアの説明](#kvs-cli-describe-keys)
+ [key-value ペアの作成](#kvs-cli-create-keys)
+ [key-value ペアの削除](#kvs-cli-delete-keys)
+ [key-value ペアの更新](#kvs-cli-update-key)

### key-value ペアの一覧表示
<a name="kvs-cli-list-keys"></a>

キーバリューストアの key-value ペアを一覧表示するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore list-keys \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**応答**

```
{
    "Items": [
        {
            "Key": "key1",
            "Value": "value1"
        }
    ]
}
```

### key-value ペアの取得
<a name="kvs-cli-get-keys"></a>

キーバリューストアの key-value ペアを取得するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore get-key \
    --key=key1 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**応答**

```
{
    "Key": "key1",
    "Value": "value1",
    "ItemCount": 1,
    "TotalSizeInBytes": 11
}
```

### キーバリューストアの説明
<a name="kvs-cli-describe-keys"></a>

キーバリューストアの説明を取得するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore describe-key-value-store \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**応答**

```
{
    "ETag": "KV1F83G8C2ARO7P",
    "ItemCount": 1,
    "TotalSizeInBytes": 11,
    "KvsARN": "arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example",
    "Created": "2024-05-08T07:48:45.381000-07:00",
    "LastModified": "2024-08-05T13:50:58.843000-07:00",
    "Status": "READY"
}
```

### key-value ペアの作成
<a name="kvs-cli-create-keys"></a>

キーバリューストアで key-value ペアを作成するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore put-key \
    --if-match=KV1PA6795UKMFR9 \
    --key=key2 \
    --value=value2 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**応答**

```
{
    "ETag": "KV13V1IB3VIYZZH",
    "ItemCount": 3,
    "TotalSizeInBytes": 31
}
```

### key-value ペアの削除
<a name="kvs-cli-delete-keys"></a>

key-value ペアのを削除するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore delete-key \
    --if-match=KV13V1IB3VIYZZH \
    --key=key1 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example
```

**出力**:

```
{
    "ETag": "KV1VC38T7YXB528",
    "ItemCount": 2,
    "TotalSizeInBytes": 22
}
```

### key-value ペアの更新
<a name="kvs-cli-update-key"></a>

単数または複数の key-value ペアを更新するには、`update-keys` コマンドを使用します。例えば、既存の key-value ペアを削除して別の key-value ペアを作成するには、次のコマンドを実行します。

```
aws cloudfront-keyvaluestore update-keys \
    --if-match=KV2EUQ1WTGCTBG2 \
    --kvs-arn=arn:aws:cloudfront::123456789012:key-value-store/37435e19-c205-4271-9e5c-example \
    --deletes '[{"Key":"key2"}]' \
    --puts '[{"Key":"key3","Value":"value3"}]'
```

**応答**

```
{
    "ETag": "KV3AEGXETSR30VB",
    "ItemCount": 3,
    "TotalSizeInBytes": 28
}
```

## key-value ペアを使用する (API)
<a name="kvs-with-functions-kvp-using-api"></a>

キーと値のペアをプログラムで操作するには、このセクションに従います。

**Contents**
+ [キーバリューストアへの参照の取得](#kvs-with-functions-api-ref)
+ [キーバリューストア内のキーと値のペアを変更する](#kvs-with-functions-api-actions)
+ [CloudFront KeyValueStore のコード例](#example-code-key-value-store)

### キーバリューストアへの参照の取得
<a name="kvs-with-functions-api-ref"></a>

CloudFront KeyValueStore API を使用して書き込みオペレーションを呼び出す際は、キーバリューストアの ARN と `ETag` を指定する必要があります。このデータを取得するには、以下を実行します。

**キーバリューストアへの参照を取得するには**

1. [https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_ListKeyValueStores.html) API オペレーションを使用して、キーバリューストアのリストを取得します。変更するキーバリューストアを見つけます。

1. [CloudFrontKeyValueStore DescribeKeyValueStore API オペレーション](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DescribeKeyValueStore.html)を使用して、前のステップからのキーバリューストアを指定します。

   この応答には、キーバリューストアの ARNと `ETag` が含まれます。
   + ARN には、次の例に示すように AWS アカウント 番号、定数 `key-value-store`、UUID が含まれます。

     `arn:aws:cloudfront::123456789012:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111`
   + `ETag` は、次の例のようになります。

     `ETVABCEXAMPLE2`

### キーバリューストア内のキーと値のペアを変更する
<a name="kvs-with-functions-api-actions"></a>

更新するキーと値のペアを含むキーバリューストアを指定できます。

次の CloudFront KeyValueStore API オペレーションを参照してください。
+ [CloudFrontKeyValueStore DeleteKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_DeleteKey.html) – キーと値のペアを削除します。
+ [CloudFrontKeyValueStore GetKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_GetKey.html) – キーと値のペアを返します。
+ [CloudFrontKeyValueStore ListKeys](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_ListKeys.html) – キーと値のペアのリストを返します。
+ [CloudFrontKeyValueStore PutKey](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_PutKey.html) – 以下のタスクを実行できます。
  + 1 つのキーバリューストアに 1 つのキーと値のペアを作成する: この場合は、新しいキー名と値を指定します。
  + 1 つの既存のキーと値のペアに別の値を設定する: この場合は、既存のキー名と新しいキー値を指定します。
+ [CloudFrontKeyValueStore UpdateKeys](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_kvs_UpdateKeys.html) – 1 つの all-or-nothing オペレーションで、以下の 1 つ以上のアクションを実行できます。
  + 1 つ以上のキーと値のペアを削除する
  + 1 つ以上のキーと値のペアを新規作成する
  + 1 つ以上の既存のキーと値のペアに別の値を設定する

### CloudFront KeyValueStore のコード例
<a name="example-code-key-value-store"></a>

**Example**  
次のコードは、キーバリューストアの `DescribeKeyValueStore` API オペレーションを呼び出す方法を示しています。  

```
const {
  CloudFrontKeyValueStoreClient,
  DescribeKeyValueStoreCommand,
} = require("@aws-sdk/client-cloudfront-keyvaluestore");

require("@aws-sdk/signature-v4-crt");

(async () => {
  try {
    const client = new CloudFrontKeyValueStoreClient({
      region: "us-east-1"
    });
    const input = {
      KvsARN: "arn:aws:cloudfront::123456789012:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111",
    };
    const command = new DescribeKeyValueStoreCommand(input);

    const response = await client.send(command);
  } catch (e) {
    console.log(e);
  }
})();
```

# CloudFront Connection Functions でカスタマイズする
<a name="customize-connections-validation-with-connection-functions"></a>

CloudFront Connection Functions を使用すると、mTLS 証明書の検証とカスタム認証ロジックのための軽量な JavaScript 関数を記述できます。Connection Functions は、mTLS 接続の確立中に実行され、クライアント証明書の検証、デバイス固有の認証ルールの実装、証明書失効シナリオの処理を行います。Connection Functions の runtime 環境は、起動時間が 1 ミリ秒未満、毎秒数百万の接続を処理するようにすぐにスケールでき、高い安全性を誇ります。Connection Functions は、CloudFront のネイティブ関数です。つまり、CloudFront 内でコードを完全に構築、テスト、デプロイできます。

Connection Function を mTLS が有効な CloudFront ディストリビューションに関連付けると、CloudFront は CloudFront エッジロケーションで TLS 接続リクエストをインターセプトし、証明書情報を関数に渡します。以下のイベントが発生したら、Connection Functions を呼び出すことができます。
+ TLS 接続の確立 (接続リクエスト) 中 - 相互 TLS (mTLS) 接続用

Connection Functions の詳細については、以下のトピックを参照してください。

**Topics**
+ [概要とワークフロー](connection-functions-overview.md)
+ [設定と制限事項](connection-function-configuration-limits.md)
+ [相互 TLS (ビューワー) 検証用の CloudFront Connection Functions を作成する](create-connection-functions.md)
+ [相互 TLS (ビューワー) 検証用の CloudFront Connection Function コードを記述する](write-connection-function-code.md)
+ [デプロイ前に CloudFront Connection Functions をテストする](test-connection-functions.md)
+ [Connection Functions をディストリビューションに関連付ける](associate-connection-functions.md)
+ [CloudFront Functions と KeyValueStore を使用して相互 TLS (ビューワー) の証明書失効を実装します](implement-certificate-revocation.md)

# 概要とワークフロー
<a name="connection-functions-overview"></a>

CloudFront Connection Functions は、クライアントが mTLS 接続を確立しようとするときに TLS ハンドシェイク中に実行される特別な種類の CloudFront Functions です。Connection Function は、クライアント証明書情報、mTLS 設定パラメータ、証明書失効チェックの結果、クライアント IP アドレスにアクセスできます。

接続関数は、CloudFront が標準証明書検証 (信頼チェーン、有効期限、署名の検証) を実行した後に呼び出されますが、証明書失効チェックが失敗した場合でも実行できます。これにより、取り消された証明書を処理するカスタムロジックを実装したり、検証基準を追加したりできます。

Connection Function を作成して公開した後、mTLS が有効なディストリビューションとの接続リクエストイベントタイプの関連付けを追加してください。これにより、クライアントが CloudFront との mTLS 接続を確立しようとするたびに関数が実行されるようになります。

CloudFront Connection Functions は、本番環境にデプロイする前に関数を開発し、テストできる 2 段階のライフサイクルに従います。このワークフローにより、ライブトラフィックに影響を与える前に Connection Functions が正しく動作します。

**Topics**
+ [関数のステージ](#connection-function-stages)
+ [開発ワークフロー](#connection-function-development-workflow)
+ [他の種類の関数との違い](#connection-function-differences)

## 関数のステージ
<a name="connection-function-stages"></a>

接続関数は、次の 2 つのステージのいずれかに存在します。
+ **開発** - このステージの関数は、変更、テスト、更新ができます。このステージを使用して、関数コードの記述およびデバッグができます。
+ **ライブ** - このステージの関数は読み取り専用で、本番環境のトラフィックを処理します。ライブステージの関数を直接変更することはできません。

新しい接続関数を作成すると、**開発**ステージで開始します。テストと検証の後、関数を発行して**ライブ**ステージに移行します。

## 開発ワークフロー
<a name="connection-function-development-workflow"></a>

このワークフローに従って、Connection Functions を開発およびデプロイします。

1. **作成** - 初期コードと設定を使用し、開発ステージで新しい接続関数を作成します。

1. **テスト** - テスト機能を使用し、デプロイ前にサンプル接続イベントで関数を検証します。

1. **更新** - テスト結果に基づき、必要に応じて関数コードと設定を変更します。

1. **発行** - 本番環境の準備ができたら、関数を公開して、開発ステージからライブステージに移行します。

1. **関連付け** - 発行された関数を mTLS が有効なディストリビューションに関連付けて、ライブ接続を処理します。

ライブの関数を変更するには、開発バージョンを更新して再度発行する必要があります。これにより、ライブステージに新しいバージョンが作成されます。

## 他の種類の関数との違い
<a name="connection-function-differences"></a>

接続関数は、いくつかの重要な点でビューワーリクエストおよびビューワーレスポンス関数とは異なります。
+ 接続関数は、HTTP 処理が発生する前、mTLS ハンドシェイクの後に実行されます
+ 接続関数は、HTTP リクエスト/レスポンスデータの代わりに TLS 証明書情報にアクセスできます
+ 接続関数は接続の許可または拒否のみを行うことができ、HTTP データを変更することはできません
+ 接続関数は、接続の再利用ではなく、新しい TLS 接続に対してのみ呼び出されます
+ TLS セッションの再開は、すべての接続で証明書の検証が行われるように、mTLS ではサポートされていません。
+ 接続関数は、標準のビューワーリクエストおよびビューワーレスポンス関数に加えて実行されます。
+ Connection Functions は、キャッシュ動作レベルではなく、ディストリビューションレベルで関連付けます。
+ 接続関数は JavaScript ランタイム 2.0 のみをサポートします。

# 設定と制限事項
<a name="connection-function-configuration-limits"></a>

CloudFront Connection Functions には、TLS 接続検証における特殊な役割とエッジコンピューティングのパフォーマンス要件により、特定の設定要件とサービスの制限があります。

**Topics**
+ [関数コードの要件](#connection-function-code-requirements)
+ [サービス制限](#connection-function-service-limits)
+ [関数のフィルタリングオプション](#connection-function-filtering-options)

## 関数コードの要件
<a name="connection-function-code-requirements"></a>

接続関数には、TLS 接続イベントを処理する JavaScript コードが必要です。関数コードは、次の条件を満たしている必要があります。
+ JavaScript で記述されている
+ 接続イベントを処理し、許可/拒否の決定を行える
+ 制限時間内に実行を完了できる
+ 証明書と接続の検証ロジックを処理できる

## サービス制限
<a name="connection-function-service-limits"></a>

接続関数には、次の制限が適用されます。
+ **関数サイズ** - 関数コードと設定のサイズは制限されています
+ **実行時間** - 関数では、TLS 接続処理の実行時間の制限が厳しくなっています
+ **関連付けの制限** - 各ディストリビューションには 1 つの Connection Function のみ関連付けることができます
+ **ステージ制限** - ライブステージ関数のみをディストリビューションに関連付けることができます

## 関数のフィルタリングオプション
<a name="connection-function-filtering-options"></a>

Connection Functions を一覧表示する場合、次のフィルターを使用できます。
+ **ステージフィルター** - 開発ステージまたはライブステージでフィルタリングする
+ **関連付けフィルター** - ディストリビューション ID またはキーバリューストア ID の関連付けでフィルタリングする

これらのフィルターは、さまざまな環境やユースケースで Connection Functions を整理および管理するのに役立ちます。

# 相互 TLS (ビューワー) 検証用の CloudFront Connection Functions を作成する
<a name="create-connection-functions"></a>

CloudFront Connection Function は、2 つのステージで作成します。

1. 関数コードを JavaScript として作成します。CloudFront コンソールのデフォルトの例を使用することも、独自に記述することもできます。詳細については、以下の各トピックを参照してください。
   + mTLS 検証用の CloudFront Connection Function コードを記述する
   + CloudFront Connection Function のイベント構造とレスポンス形式
   + 接続関数のコード例

1. CloudFront を使用して Connection Function を作成し、コードを含めます。コードは関数内にあります (リファレンスとしてではありません)。

**Topics**
+ [CloudFront コントロール](#create-connection-function-console)
+ [AWS CLI](#create-connection-function-cli)

## CloudFront コントロール
<a name="create-connection-function-console"></a>

**Connection Function を作成するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) で CloudFront コンソールを開きます。

1. [**関数の作成**] を選択してください。

1. AWS アカウント内で一意の関数名を入力し、関数タイプとして **[接続関数]** を選択し、**[続行]** を選択します。

1. 新しい Connection Function の詳細ページが表示されます。
**注記**  
接続関数は JavaScript ランタイム 2.0 のみをサポートします。関数で CloudFront Connection Function KeyValueStore 統合を使用するには、このランタイムバージョンを使用する必要があります。

1. **[関数コード]** セクションで、**[ビルド]** タブを選択し、関数コードを入力します。[ビルド] タブに含まれるサンプルコードは、Connection Function コードの基本的な構文を示しています。

1. **[Save changes]** (変更の保存) をクリックします。

1. Connection Function コードが証明書失効チェックまたはデバイス検証に KeyValueStore を使用する場合、KeyValueStore を関連付ける必要があります。

   KeyValueStore は、関数を最初に作成する時に関連付けることができます。または、後で Connection Functions を関連付けることで関連付けることができます。

   KeyValueStore を今すぐ関連付けるには、次の手順に従います。
   + **[KeyValueStore を関連付け]** セクションに移動して、**[既存の KeyValueStore を関連付け]** を選択します。
   + Connection Function の証明書データを含む KeyValueStore を選択し、次に **[KeyValueStore を関連付ける]** を選択します。

   CloudFront はストアを直ちに関数に関連付けます。関数を保存する必要はありません。

## AWS CLI
<a name="create-connection-function-cli"></a>

AWS CLI を使用する場合、通常は最初に Connection Function コードをファイルに作成し、次に AWS CLI を使用して関数を作成します。

**Connection Function を作成するには**

1. Connection Function コードをファイルに作成し、コンピュータが接続できるディレクトリに保存します。

1. 次の例に示すようにコマンドを実行します。この例では、`fileb://` 表記を使用してファイルを渡します。コマンドを読みやすくするために改行も含まれています。

   ```
   aws cloudfront create-connection-function \
       --name CertificateValidator \
       --connection-function-config '{
           "Comment":"Device certificate validation",
           "Runtime":"cloudfront-js-2.0",
           "KeyValueStoreAssociations":{
               "Quantity":1,
               "Items":[{
                   "KeyValueStoreARN":"arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111"
               }]
           }
       }' \
       --connection-function-code fileb://certificate-validator.js
   ```
**注記**  
**ランタイム** - 接続関数は JavaScript ランタイム 2.0 (cloudfront-js-2.0) のみをサポートします。
**KeyValueStoreAssociations** - Connection Function が証明書の検証に KeyValueStore を使用する場合、関数の初回作成時に KeyValueStore を関連付けることができます。または、後で update-connection-function を使用して関連付けることもできます。各 Connection Function に関連付けることができる KeyValueStore は 1 つだけのため、Quantity は常に 1 です。

1. コマンドが成功した場合は、以下のような出力が表示されます。

   ```
   ETag: ETVABCEXAMPLE
   ConnectionFunctionSummary:
     ConnectionFunctionConfig:
       Comment: Device certificate validation
       Runtime: cloudfront-js-2.0
       KeyValueStoreAssociations:
         Quantity: 1
         Items:
           - KeyValueStoreARN: arn:aws:cloudfront::111122223333:key-value-store/a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
     ConnectionFunctionMetadata:
       CreatedTime: '2024-09-04T16:32:54.292000+00:00'
       ConnectionFunctionARN: arn:aws:cloudfront::111122223333:connection-function/CertificateValidator
       LastModifiedTime: '2024-09-04T16:32:54.292000+00:00'
       Stage: DEVELOPMENT
     Name: CertificateValidator
     Status: UNPUBLISHED
   Location: https://cloudfront.amazonaws.com/2020-05-31/connection-function/arn:aws:cloudfront:::connection-function/CertificateValidator
   ```

   ほとんどの情報はリクエストから繰り返されます。その他の情報は CloudFront によって追加されます。
**注記**  
**ETag** - この値は、Connection Function を変更するたびに変わります。関数を更新または公開するには、この値が必要です。
**ステージ** - 新しい接続関数は開発ステージで開始されます。関数をディストリビューションに関連付ける前に発行してライブステージに移行する必要があります。
**ステータス** - 関数のステータスは、ライブステージに発行するまで未発行です。

# 相互 TLS (ビューワー) 検証用の CloudFront Connection Function コードを記述する
<a name="write-connection-function-code"></a>

CloudFront Connection Functions により、mTLS 証明書の検証とカスタム認証ロジックのための軽量な JavaScript 関数を記述できます。Connection Function コードは、クライアント証明書の検証、デバイス固有の認証ルールの実装、証明書失効シナリオの処理、世界中の CloudFront エッジロケーションでの TLS 接続の許可/拒否の決定を行うことができます。

接続関数は、CloudFront の組み込み証明書検証を独自のビジネスロジックで拡張する強力な方法を提供します。HTTP データを処理するビューワーリクエストおよびビューワーレスポンス関数とは異なり、Connection Functions は TLS レイヤーで動作し、証明書情報、クライアント IP アドレス、TLS 接続の詳細にアクセスできます。これは、標準 PKI 検証を超えるゼロトラストセキュリティモデル、デバイス認証システム、カスタム証明書検証ポリシーの実装に適しています。

Connection Function コードは、1 ミリ秒未満のスタートアップ時間で安全に隔離された環境で実行され、1 秒あたり数百万の接続を処理するようにスケーリングできます。ランタイムは証明書検証ワークロードのために最適化されており、CloudFront KeyValueStore との組み込み統合によりリアルタイムのデータ検索オペレーションが可能になり、証明書失効リストのチェックやデバイス許可リストの検証などの高度な認証シナリオが可能になります。

効果的な Connection Function コードを記述するには、以下のトピックを参照してください。完全なコード例とステップバイステップのチュートリアルについては、このガイドのチュートリアルセクションを参照し、CloudFront コンソールで利用可能な Connection Function の例を確認してください。

**Topics**
+ [CloudFront Connection Function のユースケースと目的](#connection-function-use-cases)
+ [CloudFront Connection Function のイベント構造とレスポンス形式](#connection-function-event-structure)
+ [CloudFront Connection Functions の JavaScript ランタイムの機能](#connection-function-javascript-runtime)
+ [CloudFront Connection Function のヘルパーメソッドと API](#connection-function-helper-methods)
+ [CloudFront Connection Function KeyValueStore の統合](#connection-function-kvs-integration)
+ [async および await を使用します](#connection-function-async-await)
+ [接続関数のコード例](#connection-function-code-examples)

## CloudFront Connection Function のユースケースと目的
<a name="connection-function-use-cases"></a>

CloudFront Connection Function を記述する前に、実装する必要がある証明書の検証または認証ロジックのタイプを慎重に決定してください。接続関数は、標準の PKI 証明書チェックを超えたカスタム検証を必要とする特定のユースケース向けに設計されています。ユースケースを理解すると、最適なパフォーマンスを維持しながら、セキュリティ要件を満たす効率的なコードを設計できます。

Connection Function の一般的なユースケースは次のとおりです。
+ **証明書失効の処理** - 失効した証明書を処理するためのカスタムポリシーを実装します。これには、証明書のローテーションの猶予期間、内部デバイスの信頼されたネットワークの例外、失効した証明書に一時的なアクセスが必要になる可能性がある緊急アクセスシナリオが含まれます。
+ **オプションの mTLS サポート** - mTLS 接続と非 mTLS 接続の両方を異なる認証ポリシーで処理するため、レガシークライアントとの互換性を維持しながら、証明書をサポートするクライアントのセキュリティを強化できます。
+ **IP ベースの認証** - 証明書の検証をクライアント IP アドレスのチェックと組み合わせて、特定の地理的リージョン、企業ネットワーク、既知の悪意のある IP 範囲からのアクセスを制限するなど、セキュリティを強化します。
+ **マルチテナント証明書の検証** - クライアント証明書の発行者またはサブジェクト属性に基づいて異なる認証局または検証基準が適用されるテナント固有の検証ルールを実装します。
+ **時間ベースのアクセスコントロール** - 証明書自体の有効期限が切れていない場合でも、証明書が特定の時間、メンテナンスウィンドウ、または事業期間中にのみ有効な時間ベースの制限を適用します。

接続関数は、CloudFront が標準証明書検証 (信頼チェーンの検証、有効期限のチェック、署名の検証) を実行した後、TLS 接続が確立される前に実行されます。このタイミングにより、CloudFront の組み込み証明書検証のメリットを享受しながら、カスタム検証基準を柔軟に追加できます。関数は標準検証の結果を受け取り、標準基準とカスタム基準の両方に基づいて接続を許可または拒否するかどうかについて、情報に基づいた決定を行うことができます。

Connection Function を設計する場合、検証ロジックのパフォーマンスへの影響を検討してください。関数の実行制限は 5 ミリ秒であるため、複雑なオペレーションは速度に合わせて最適化する必要があります。複雑な計算ではなく高速なデータ検索に KeyValueStore を使用し、無効な証明書のフェイルファストに検証ロジックを構築します。

## CloudFront Connection Function のイベント構造とレスポンス形式
<a name="connection-function-event-structure"></a>

CloudFront Connection Functions は、ビューワーリクエストおよびビューワーレスポンス関数とは異なるイベント構造を受け取ります。HTTP リクエスト/レスポンスデータの代わりに、接続関数は認証の決定に使用できる証明書と接続情報を受け取ります。

**Topics**
+ [Connection Functions のイベント構造](#connection-function-event-structure-details)
+ [Connection Functions のレスポンス形式](#connection-function-response-format)

### Connection Functions のイベント構造
<a name="connection-function-event-structure-details"></a>

Connection Functions は、証明書と接続情報を含むイベントオブジェクトを受け取ります。関数のイベント構造を以下に示します。

```
{
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "serialNumber": "string",
        "issuer": "string",
        "subject": "string",
        "validity": {
          "notBefore": "string",
          "notAfter": "string",
        },
        "sha256Fingerprint": "string"
      }
    }
  },
  "clientIp": "string",
  "endpoint": "string",
  "distributionId": "string",
  "connectionId": "string"
}
```

以下に、イベントオブジェクトの構造の例を示します。

```
{
  "clientCertificate": {
    "certificates": {
      "leaf": {
        "serialNumber": "00:9e:2a:af:16:56:e5:47:25:7d:2e:38:c3:f9:9d:57:fa",
        "issuer": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie",
        "subject": "C=US, O=Ram, OU=Edge, ST=WA, CN=mTLS-CA, L=Snoqualmie",
        "validity": {
          "notBefore": "2025-09-10T23:43:10Z",
          "notAfter": "2055-09-11T00:43:02Z"
        },
        "sha256Fingerprint": "_w6bJ7aOAlGOj7NUhJxTfsfee-ONg_xop3_PTgTJpqs="
      }
    }
  },
  "clientIp": "127.0.0.1",
  "endpoint": "d3lch071jze0cb.cloudfront.net",
  "distributionId": "E1NXS4MQZH501R",
  "connectionId": "NpvTe1925xfj24a67sPQr7ae42BIq03FGhJJKfrQYWZcWZFp96SIIg=="
}
```

### Connection Functions のレスポンス形式
<a name="connection-function-response-format"></a>

Connection Function は、接続を許可または拒否するかを示すレスポンスオブジェクトを返す必要があります。ヘルパーメソッドを使用して接続の決定を行います。

```
function connectionHandler(connection) {
    // Helper methods to allow or deny connections
    if (/* some logic to determine if function should allow connection */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```

ビューワーリクエストおよびビューワーレスポンス関数とは異なり、Connection Functions は HTTP リクエストまたはレスポンスを変更できません。TLS 接続のみを許可または拒否できます。

## CloudFront Connection Functions の JavaScript ランタイムの機能
<a name="connection-function-javascript-runtime"></a>

CloudFront Connection Functions は CloudFront Functions JavaScript ランタイム 2.0 を使用します。これは、証明書検証ワークロード用に特別に最適化された安全で高性能な環境を提供します。ランタイムは、ミリ秒未満で開始し、CloudFront のグローバルエッジネットワーク全体で数百万の同時実行を処理するように設計されています。

ランタイム環境には、包括的な JavaScript 言語のサポートが含まれています。
+ **ECMAScript 2020 (ES11) サポート** - オプションの連鎖 (?.)、NULL 合体 (??)、大規模な証明書のシリアル番号を処理する BigInt などの最新の JavaScript 機能
+ **組み込みオブジェクト** - オブジェクト、配列、JSON、Math、日付などの標準 JavaScript オブジェクト
+ **コンソールログ記録** - console.log() を使用して、証明書検証の決定をデバッグおよびモニタリングします。ログはテスト中にリアルタイムで利用でき、開発中の検証ロジックのトラブルシューティングに役立ちます。
+ **KeyValueStore 統合** - 超高速データ検索オペレーションのための CloudFront KeyValueStore へのネイティブアクセスにより、証明書失効のリアルタイムチェック、デバイス許可リストの検証、テナント固有の設定の取得を可能にします。

接続関数は、高性能な証明書検証のシナリオに最適化されています。ランタイムはメモリ管理、ガベージコレクション、リソースクリーンアップを自動的に処理し、数百万の同時接続において安定したパフォーマンスを確保します。すべてのオペレーションは確定的で高速に設計されており、KeyValueStore 検索は通常マイクロ秒で完了します。

ランタイム環境は関数の実行間で完全に分離されるため、異なるクライアント接続間でデータリークが発生することはありません。各関数の実行はクリーン状態から開始され、以前の実行結果や他の接続からのクライアントデータにアクセスすることはありません。

## CloudFront Connection Function のヘルパーメソッドと API
<a name="connection-function-helper-methods"></a>

CloudFront Connection Functions は、証明書の検証の決定を簡素化し、オブザーバビリティを強化するように設計された特殊なヘルパーメソッドを提供します。これらのメソッドは、接続検証ワークフローに最適化されており、CloudFront の接続ログ記録およびモニタリングシステムとシームレスに統合されます。
+ **connection.allow()** - TLS 接続の続行を許可します。このメソッドは、TLS ハンドシェイクを完了するよう CloudFront にシグナルを送信し、クライアントが接続を確立できるようにします。これは、証明書の検証に合格し、カスタム認証ロジックが満たされた場合に使用します。
+ **connection.deny()** - TLS 接続を拒否し、ハンドシェイクを終了します。このメソッドは、すぐに接続を終了し、HTTP トラフィックが流れるのを防ぎます。クライアントは TLS 接続エラーを受け取ります。これは、無効な証明書、認証の失敗、またはポリシー違反に使用します。
+ **connection.logCustomData()** - 接続ログにカスタムデータを追加します (最大 800 バイトの UTF-8 テキスト)。この方法により、セキュリティのモニタリング、コンプライアンス監査、トラブルシューティングのために、検証結果、証明書の詳細、または決定の根拠を CloudFront 接続ログに含めることができます。

これらのメソッドは、接続の決定を行い、モニタリングとデバッグに関連する情報のログを記録するためのクリーンで宣言型のインターフェイスを提供します。許可/拒否パターンにより、関数のインテントが明確になり、CloudFront が決定に基づいて接続処理を最適化できるようになります。カスタムログ記録データは CloudFront 接続ログですぐに利用でき、セキュリティモニタリングと運用のインサイトのためのログ分析ツールで使用できます。

関数が完了する前に、必ず connection.allow() または connection.deny() を呼び出してください。いずれのメソッドも呼び出されない場合、CloudFront はセキュリティ上の予防策としてデフォルトで接続を拒否します。

## CloudFront Connection Function KeyValueStore の統合
<a name="connection-function-kvs-integration"></a>

CloudFront Connection Functions は CloudFront KeyValueStore を使用して、証明書検証シナリオの超高速データ検索を実行できます。KeyValueStore は、すべての CloudFront エッジロケーションにわたり、マイクロ秒の検索時間でグローバルで結果整合性のあるデータアクセスを提供するため、Connection Functions にとって特に強力です。これにより、証明書失効リスト、デバイスの許可リスト、テナント設定、および TLS ハンドシェイク中にアクセスする必要がある他の検証データを維持するのに最適です。

KeyValueStore 統合は、高性能の接続検証ワークフロー専用に設計されています。
+ **kvsHandle.exists(キー)** - 値を取得せずに KeyValueStore にキーが存在するかどうかを確認します。これは、証明書のシリアル番号が失効リストにあるかどうかのみを知る必要がある証明書失効チェックなどのバイナリ検証シナリオに最も効率的な方法です。
+ **kvsHandle.get(キー)** - より複雑な検証シナリオのために KeyValueStore から値を取得します。これは、証明書またはデバイス識別子に関連付けられた設定データ、検証ルール、またはメタデータにアクセスする必要がある場合に使用します。

KeyValueStore オペレーションは非同期であり、非同期/待機構文で使用する必要があります。KeyValueStore の合計サイズ制限は 10 MB で、最大 1,000 万個のキーと値のペアをサポートします。KeyValueStore データはすべてのエッジロケーションで結果的に整合性があり、更新は通常数秒以内に伝播されます。

最適なパフォーマンスを得るには、KeyValueStore キーを構造化して検索オペレーションを最小限にします。シンプルな失効チェックのキーとして証明書のシリアル番号を使用するか、マルチ CA 環境の発行者のハッシュとシリアル番号を組み合わせた複合キーを作成します。データ構造を設計するときは、キーの複雑さと KeyValueStore 容量のトレードオフを考慮してください。

## async および await を使用します
<a name="connection-function-async-await"></a>

接続関数は、async/await 構文を使用した非同期オペレーションをサポートします。これは、KeyValueStore オペレーションや他の非同期タスクを操作するときに必要です。async/await パターンにより、TLS ハンドシェイク処理に必要な高性能の特徴を維持しながら、関数は接続の決定を行う前に KeyValueStore の検索が完了するまで待機します。

KeyValueStore オペレーションは非常に高速ですが、CloudFront の分散インフラストラクチャ全体で調整の必要があるネットワークオペレーションであるため、Connection Functions では適切な async/await の使用が重要です。ランタイムは promise の解決を自動的に処理し、関数が 5 ミリ秒の実行制限内に完了するようにします。

**Example : 非同期 の Connection Function と KeyValueStore**  

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Async operation to check KeyValueStore for certificate revocation
    const isRevoked = await kvsHandle.exists(connection.clientCertificate.certificates.leaf.serialNumber);
    
    if (isRevoked) {
        // Log the revocation decision with certificate details
        connection.logCustomData(`REVOKED_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}:${connection.clientCertificate.certificates.leaf.issuer}`);
        console.log(`Denying connection for revoked certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`);
        return connection.deny();
    }
    
    // Log successful validation for monitoring
    connection.logCustomData(`VALID_CERT:${connection.clientCertificate.certificates.leaf.serialNumber}`);
    console.log(`Allowing connection for valid certificate: ${connection.clientCertificate.certificates.leaf.serialNumber}`);
    return connection.allow();
}
```

KeyValueStore メソッドや他の非同期オペレーションを呼び出すときは、常に async/await を使用します。Connection Function ランタイムは promise の解決を自動的に処理し、TLS ハンドシェイク処理の厳密なタイミング制約内で適切な実行フローを確保します。async/await により Connection Function 環境でのよりクリーンなエラー処理とパフォーマンスが向上しますので、.then() またはコールバックパターンの使用は避けてください。

非同期の Connection Functions を設計するときは、KeyValueStore オペレーションの数が最小限になるようにコードを構築し、検証ロジックのできるだけ早い段階で実行します。これにより、パフォーマンスが最大になり、トラフィックの多い時間帯にタイムアウトの問題が発生するリスクが軽減されます。関連する検証チェックをバッチ処理し、ユースケースに最も効率的な KeyValueStore メソッド (exists() と get()) を使用することを検討してください。

## 接続関数のコード例
<a name="connection-function-code-examples"></a>

以下の例は、さまざまな検証シナリオで一般的な Connection Function パターンを示しています。これらの例を、独自の Connection Function 実装の開始点として使用します。

**Example : デバイスの証明書の検証**  
この例では、IoT デバイス、ゲームコンソール、および他のクライアント認証シナリオのデバイスのシリアル番号と証明書のサブジェクトフィールドを検証します。  

```
async function connectionHandler(connection) {
    // Custom validation: check device serial number format
    const serialNumber = connection.clientCertificate.certificates.leaf.serialNumber;
    if (!serialNumber.startsWith("DEV")) {
        connection.logCustomData(`INVALID_SERIAL:${serialNumber}`);
        return connection.deny();
    }
    
    // Validate certificate subject contains required organizational unit
    const subject = connection.clientCertificate.certificates.leaf.subject;
    if (!subject.includes("OU=AuthorizedDevices")) {
        connection.logCustomData(`INVALID_OU:${subject}`);
        return connection.deny();
    }
    
    // Allow connection for valid devices
    connection.logCustomData(`VALID_DEVICE:${serialNumber}`);
    return connection.allow();
}
```
この関数は、デバイスのシリアル番号形式や組織単位の検証など、標準証明書の検証を超えて複数の検証チェックを実行します。

**Example : 混合認証を使用したオプションの mTLS**  
この例では、異なる認証ポリシーを使用して mTLS 接続と非 mTLS 接続の両方を処理します。  

```
async function connectionHandler(connection) {
    if (connection.clientCertificate) {
        // mTLS connection - enhanced validation for certificate holders
        const subject = connection.clientCertificate.certificates.leaf.subject;
        connection.logCustomData(`MTLS_SUCCESS:${subject}:${connection.clientIp}`);
        console.log(`mTLS connection from: ${subject}`);
        return connection.allow();
    } else {
        // Non-mTLS connection - apply IP-based restrictions
        const clientIp = connection.clientIp;
        
        // Only allow non-mTLS from specific IP ranges
        if (clientIp.startsWith("203.0.113.") || clientIp.startsWith("198.51.100.")) {
            connection.logCustomData(`NON_MTLS_ALLOWED:${clientIp}`);
            console.log(`Non-mTLS connection allowed from: ${clientIp}`);
            return connection.allow();
        }
        
        connection.logCustomData(`NON_MTLS_DENIED:${clientIp}`);
        return connection.deny();
    }
}
```
この関数は、信頼できる IP 範囲のレガシークライアントとの互換性を維持しながら、証明書を持つクライアントのセキュリティを強化します。

# デプロイ前に CloudFront Connection Functions をテストする
<a name="test-connection-functions"></a>

TestConnectionFunction API オペレーションを使用して、開発ステージで CloudFront Connection Functions をテストできます。テストでは、ライブステージに発行する前に、サンプル接続イベントで関数ロジックを検証できます。

**Topics**
+ [テストのプロセス](#connection-function-testing-process)
+ [テスト結果](#connection-function-test-results)
+ [接続テストオブジェクト](#connection-test-object)

## テストのプロセス
<a name="connection-function-testing-process"></a>

Connection Function をテストするには

1. 開発ステージで Connection Function を作成します

1. TLS 接続イベントを表すテスト接続オブジェクトを準備します

1. TestConnectionFunction API オペレーションを使用して、テストデータで関数を実行します

1. 関数出力、実行ログ、エラーメッセージなどのテスト結果を確認します

1. 必要に応じて関数コードを更新し、テストプロセスを繰り返します

## テスト結果
<a name="connection-function-test-results"></a>

Connection Function をテストすると、次のような結果になります。
+ **関数の概要** - テストされた関数に関するメタデータ
+ **コンピューティング使用率** - リソース使用状況を示すパフォーマンスメトリクス
+ **実行ログ** - ログ記録ステートメントを含む、関数からのコンソール出力
+ **関数の出力** - 関数によって返される結果
+ **エラーメッセージ** - 実行中に発生したランタイムエラーまたは例外

## 接続テストオブジェクト
<a name="connection-test-object"></a>

接続テストオブジェクトは、関数が処理する TLS 接続イベントを表すバイナリ BLOB (最大 40KB) です。このオブジェクトには、関数が認証の決定を行うために使用する証明書と接続情報が含まれています。

**注記**  
接続テストオブジェクトの特定の構造と形式は、CloudFront Connection Functions ランタイムによって定義されます。ユースケースに適切なテストオブジェクトの作成に関する詳細については、CloudFront Functions のドキュメントを参照するか、AWS サポート にお問い合わせください。

Connection Function を作成したら、次のことができます。
+ **関数のテスト** - コンソールまたは CLI のテスト機能を使用して、サンプル接続イベントで関数を検証できます。詳細については、「Connection Function のテスト」を参照してください。
+ **関数の更新** - 必要に応じて関数コードと設定を変更できます。開発ステージの接続関数はいつでも更新できます。
+ **関数の公開** - 本番環境の準備ができたら、関数を発行して、開発ステージからライブステージに移行できます。詳細については、「Connection Function の関連付け」を参照してください。
+ **ディストリビューションとの関連付け** - 発行された関数を mTLS が有効なディストリビューションに関連付けて、ライブ接続を処理できます。詳細については、「接続関数の関連付け」を参照してください。

# Connection Functions をディストリビューションに関連付ける
<a name="associate-connection-functions"></a>

Connection Function をライブステージに発行した後、ライブ接続を処理できるようにするには、mTLS が有効なディストリビューションに関連付ける必要があります。接続関数は、キャッシュ動作に関連付けられているビューワーリクエストやビューワーレスポンス関数とは異なり、ディストリビューションレベルで関連付けられます。

**Topics**
+ [関連付けの要件](#connection-function-association-requirements)
+ [フィルターを使用した関数の整理](#connection-function-organizing-filters)
+ [デプロイに関する考慮事項](#connection-function-deployment-considerations)

## 関連付けの要件
<a name="connection-function-association-requirements"></a>

Connection Function をディストリビューションに関連付けるには
+ 関数はライブステージである必要があります
+ ディストリビューションで mTLS が有効になっている必要があります
+ ディストリビューションには有効なトラストストアが設定されている必要があります
+ ディストリビューションごとに関連付けることができる Connection Function は 1 つだけです

## フィルターを使用した関数の整理
<a name="connection-function-organizing-filters"></a>

CloudFront は、接続関数の整理と管理に役立つフィルタリング機能を提供します。
+ **ディストリビューション ID フィルター** - 特定のディストリビューションに関連付けられた関数を検索します
+ **キーバリューストアのフィルター** - データ検索に特定のキーバリューストアを使用する関数を検索します
+ **ステージフィルター** - 開発ステージまたはライブステージの関数を一覧表示します

異なるディストリビューションまたは開発環境間で複数の Connection Functions を管理する場合に、これらのフィルターを使用します。

## デプロイに関する考慮事項
<a name="connection-function-deployment-considerations"></a>

Connection Functions をデプロイする場合、次の要素を考慮してください。
+ **グローバルデプロイ** - 接続関数は世界中のすべての CloudFront エッジロケーションにデプロイされ、これには数分かかる場合があります
+ **バージョン管理** – 各公開バージョンは、以前のバージョンを置き換える新しい LIVE 関数を作成します
+ **ロールバック戦略** - 関数コードの以前の作業バージョンを保持してロールバックを計画します
+ **本番環境でのテスト** - ステージング環境と本番環境に別々のディストリビューションを使用することを検討してください

# CloudFront Functions と KeyValueStore を使用して相互 TLS (ビューワー) の証明書失効を実装します
<a name="implement-certificate-revocation"></a>

KeyValueStore で CloudFront Connection Functions を使用して、証明書失効チェックを実装できます。これにより、失効した証明書のシリアル番号のリストを維持し、TLS ハンドシェイク中にクライアント証明書とこのリストを確認できます。

証明書失効を実装するには、次のコンポーネントが必要です。
+ ビューワー mTLS で設定されたディストリビューション
+ 失効した証明書のシリアル番号を含む KeyValueStore
+ KeyValueStore にクエリを実行して証明書のステータスを確認する Connection Function

クライアントが接続されると、CloudFront はトラストストアに対して証明書を検証し、Connection Function を実行します。関数は証明書のシリアル番号と KeyValueStore を確認し、接続を許可または拒否します。

**Topics**
+ [ステップ 1: 失効した証明書の KeyValueStore を作成する](create-kvs-revoked-certificates.md)
+ [ステップ 2: 失効 Connection Function を作成する](create-revocation-connection-function.md)
+ [ステップ 3: 失効関数をテストする](test-revocation-function.md)
+ [ステップ 4: 関数をディストリビューションに関連付ける](associate-function-distribution.md)
+ [高度な失効シナリオ](advanced-revocation-scenarios.md)

# ステップ 1: 失効した証明書の KeyValueStore を作成する
<a name="create-kvs-revoked-certificates"></a>

mTLS 接続中に Connection Function が確認できる失効した証明書のシリアル番号を保存する KeyValueStore を作成します。

まず、失効した証明書のシリアル番号を JSON 形式で準備します。

```
{
  "data": [
    {
      "key": "ABC123DEF456",
      "value": ""
    },
    {
      "key": "789XYZ012GHI", 
      "value": ""
    }
  ]
}
```

この JSON ファイルを S3 バケットにアップロードし、KeyValueStore を作成します。

```
aws s3 cp revoked-serials.json s3://your-bucket-name/revoked-serials.json
aws cloudfront create-key-value-store \
  --name revoked-serials-kvs \
  --import-source '{
    "SourceType": "S3",
    "SourceARN": "arn:aws:s3:::your-bucket-name/revoked-serials.json"
  }'
```

KeyValueStore がプロビジョニングを完了するまで待ちます。次の方法でステータスを確認します。

```
aws cloudfront get-key-value-store --name "revoked-serials-kvs"
```

# ステップ 2: 失効 Connection Function を作成する
<a name="create-revocation-connection-function"></a>

証明書のシリアル番号と KeyValueStore を確認し、証明書が失効しているかどうかを決定する Connection Function を作成します。

証明書のシリアル番号と KeyValueStore を確認する Connection Function を作成します。

```
aws cloudfront create-connection-function \
  --name "revocation-control" \
  --connection-function-config file://connection-function-config.json \
  --connection-function-code file://connection-function-code.txt
```

設定ファイルで KeyValueStore の関連付けを指定します。

```
{
  "Runtime": "cloudfront-js-2.0",
  "Comment": "A function that implements revocation control via KVS",
  "KeyValueStoreAssociations": {
    "Quantity": 1,
    "Items": [
      {
        "KeyValueStoreArn": "arn:aws:cloudfront::account-id:key-value-store/kvs-id"
      }
    ]
  }
}
```

Connection Function コードは、失効した証明書について KeyValueStore を確認します。

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    
    // Get parsed client serial number from client certificate
    const clientSerialNumber = connection.clientCertInfo.serialNumber;
    
    // Check KVS to see if serial number exists as a key
    const serialNumberExistsInKvs = await kvsHandle.exists(clientSerialNumber);
    
    // Deny connection if serial number exists in KVS
    if (serialNumberExistsInKvs) {
        console.log("Connection denied - certificate revoked");
        return connection.deny();
    }
    
    // Allow connections that don't exist in kvs
    console.log("Connection allowed");
    return connection.allow();
}
```

# ステップ 3: 失効関数をテストする
<a name="test-revocation-function"></a>

CloudFront コンソールを使用し、サンプル証明書を使用して Connection Function をテストします。コンソールの Connection Function に移動し、[テスト] タブを使用します。

**サンプル証明書を使用してテストする**

1. PEM 形式のサンプル証明書をテストインターフェイスに貼り付ける

1. オプションで、IP ベースのロジックをテストするクライアント IP アドレスを指定します。

1. **[関数をテスト]** を選択して、実行結果を表示します。

1. 実行ログを確認し、関数ロジックを検証する

有効な証明書と失効した証明書の両方を使用してテストし、関数が両方のシナリオを正しく処理することを確認します。実行ログには、console.log 出力と、関数の実行中に発生したエラーが表示されます。

# ステップ 4: 関数をディストリビューションに関連付ける
<a name="associate-function-distribution"></a>

Connection Function を発行したら、mTLS が有効なディストリビューションに関連付けて、証明書失効チェックを有効にします。

関数は、ディストリビューション設定ページ、または Connection Function の関連付けられたディストリビューションテーブルから関連付けることができます。ディストリビューション設定に移動し、**[ビューワーの相互認証 (mTLS)]** セクションまでスクロールし、Connection Function を選択して変更を保存します。

# 高度な失効シナリオ
<a name="advanced-revocation-scenarios"></a>

より複雑な証明書失効の要件については、次の追加の設定を検討してください。

**Topics**
+ [証明書失効リスト (CRL) を KeyValueStore 形式に変換する](#convert-crl-kvs-format)
+ [複数の認証局を処理する](#handle-multiple-cas)
+ [接続ログにカスタムデータを追加する](#add-custom-data-logs)
+ [CRL の更新を管理する](#manage-crl-updates)
+ [KeyValueStore 容量を計画する](#plan-kvs-capacity)

## 証明書失効リスト (CRL) を KeyValueStore 形式に変換する
<a name="convert-crl-kvs-format"></a>

証明書失効リスト (CRL) ファイルがある場合は、OpenSSL と jq を使用して KeyValueStore JSON 形式に変換できます。

**CRL を KeyValueStore 形式に変換する**

CRL ファイルからシリアル番号を抽出します。

```
openssl crl -text -noout -in rfc5280_CRL.crl | \
  awk '/Serial Number:/ {print $3}' | \
  cut -d'=' -f2 | \
  sed 's/../&:/g;s/:$//' >> serialnumbers.txt
```

シリアル番号を KeyValueStore JSON 形式に変換します。

```
jq -R -s 'split("\n") | map(select(length > 0)) | {data: map({"key": ., "value": ""})}' \
  serialnumbers.txt >> serialnumbers_kvs.json
```

ステップ 1 の説明に従って、フォーマットされたファイルを S3 にアップロードし、KeyValueStore を作成します。

## 複数の認証局を処理する
<a name="handle-multiple-cas"></a>

TrustStore に複数の認証局 (CA) が含まれている場合は、同じシリアル番号を持つ異なる CA からの証明書間の競合を避けるために、KeyValueStore キーに発行者情報を含めます。

マルチ CA シナリオでは、発行者の SHA1 ハッシュとシリアル番号の組み合わせをキーとして使用します。

```
import cf from 'cloudfront';

async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    const clientCert = connection.clientCertInfo;
    
    // Create composite key with issuer hash and serial number
    const issuer = clientCert.issuer.replace(/[^a-zA-Z0-9]/g, '').substring(0, 20);
    const serialno = clientCert.serialNumber;
    const compositeKey = `${issuer}_${serialno}`;
    
    const cert_revoked = await kvsHandle.exists(compositeKey);
    
    if (cert_revoked) {
        console.log(`Blocking revoked cert: ${serialno} from issuer: ${issuer}`);
        connection.deny();
    } else {
        connection.allow();
    }
}
```

**注記**  
発行者識別子とシリアル番号を使用すると、キーが長くなるため、KeyValueStore に保存できるエントリの合計数が少なくなる可能性があります。

## 接続ログにカスタムデータを追加する
<a name="add-custom-data-logs"></a>

接続関数は、logCustomData メソッドを使用して CloudFront 接続ログにカスタムデータを追加できます。これにより、失効チェックの結果、証明書情報、または他の関連データをログに含めることができます。

```
async function connectionHandler(connection) {
    const kvsHandle = cf.kvs();
    const clientSerialNumber = connection.clientCertInfo.serialNumber;
    const serialNumberExistsInKvs = await kvsHandle.exists(clientSerialNumber);
    
    if (serialNumberExistsInKvs) {
        // Log revocation details to connection logs
        connection.logCustomData(`REVOKED:${clientSerialNumber}:DENIED`);
        console.log("Connection denied - certificate revoked");
        return connection.deny();
    }
    
    // Log successful validation
    connection.logCustomData(`VALID:${clientSerialNumber}:ALLOWED`);
    console.log("Connection allowed");
    return connection.allow();
}
```

カスタムデータは、有効な UTF-8 テキスト 800 バイトに制限されています。この制限を超えると、CloudFront はデータを最も近い有効な UTF-8 境界に切り捨てます。

**注記**  
カスタムデータログ記録は、ディストリビューションで接続ログが有効になっている場合にのみ機能します。接続ログが設定されていない場合、logCustomData メソッドは no-op です。

## CRL の更新を管理する
<a name="manage-crl-updates"></a>

認証局は 2 種類の CRL を発行できます。
+ **完全な CRL**: 失効したすべての証明書の完全なリストを含みます
+ **デルタ CRL**: 前回の完全な CRL 以降に失効した証明書のみを一覧表示します

完全な CRL を更新するには、更新されたデータを使用して新しい KeyValueStore を作成し、Connection Function の関連付けを新しい KeyValueStore にリダイレクトします。このアプローチは、違いを計算し、増分更新を実行するよりもシンプルです。

デルタ CRL を更新するには、update-keys コマンドを使用して、新しく失効した証明書を既存の KeyValueStore に追加します。

```
aws cloudfront update-key-value-store \
  --name "revoked-serials-kvs" \
  --if-match "current-etag" \
  --put file://delta-revoked-serials.json
```

## KeyValueStore 容量を計画する
<a name="plan-kvs-capacity"></a>

KeyValueStore の合計サイズ制限は 5 MB で、最大 1,000 万個のキーと値のペアをサポートします。キー形式とデータサイズに基づいて、失効リストの容量を計画します。
+ **シリアル番号のみ**: シンプルな失効チェックのための効率的なストレージ
+ **発行者識別子とシリアル番号**: マルチ CA 環境のための長いキー

大規模な失効リストの場合は、異なる証明書カテゴリまたは期間に対して別々の KeyValueStores を維持する階層型アプローチの実装を検討してください。

# Lambda@Edge を使用してエッジでカスタマイズする
<a name="lambda-at-the-edge"></a>

Lambda@Edge は AWS Lambda の拡張です。Lambda@Edge は、Amazon CloudFront が配信するコンテンツをカスタマイズする関数を実行できるコンピューティングサービスです。Node.js または Python 関数は、Lambda コンソールで 1 つの AWS リージョン、米国東部 (バージニア北部) で作成できます。

関数を作成したら、Lambda コンソールまたは CloudFront コンソールを使用してトリガーを追加し、サーバーをプロビジョニングまたは管理することなく、ビューワーに近い AWS ロケーションで関数を実行できます。オプションで、Lambda および CloudFront API オペレーションを使用して、関数とトリガーをプログラムで設定できます。

Lambda@Edge は、1 日あたり数個のリクエストから 1 秒あたり数千のリクエストまで自動的にスケーリングします。オリジンサーバーの代わりに、ビューワーの最寄りの AWS ロケーションでリクエストを処理すると、レイテンシーが大幅に軽減され、ユーザーエクスペリエンスが向上します。

**注記**  
Lambda@Edge は gRPC リクエストではサポートされていません。詳細については、「[CloudFront ディストリビューションでの gRPC の使用](distribution-using-grpc.md)」を参照してください。

**Topics**
+ [Lambda@Edge がリクエストとレスポンスで機能する仕組み](lambda-edge-event-request-response.md)
+ [Lambda@Edge の使用方法](lambda-edge-ways-to-use.md)
+ [Lambda@Edge 関数の使用を開始する (コンソール)](lambda-edge-how-it-works.md)
+ [Lambda@Edge 用の IAM アクセス許可とロールのセットアップ](lambda-edge-permissions.md)
+ [Lambda@Edge 関数を記述および作成する](lambda-edge-create-function.md)
+ [Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)
+ [Lambda@Edge 関数をテストおよびデバッグする](lambda-edge-testing-debugging.md)
+ [Lambda@Edge 関数とレプリカを削除する](lambda-edge-delete-replicas.md)
+ [Lambda@Edge イベント構造](lambda-event-structure.md)
+ [リクエストとレスポンスを使用する](lambda-generating-http-responses.md)
+ [Lambda@Edge 関数の例](lambda-examples.md)

# Lambda@Edge がリクエストとレスポンスで機能する仕組み
<a name="lambda-edge-event-request-response"></a>

CloudFront ディストリビューションを Lambda@Edge 関数に関連付けると、CloudFront エッジロケーションでリクエストとレスポンスがインターセプトされます。Lambda 関数は、次の CloudFront イベントの発生時に実行できます。
+ CloudFront がビューワーからリクエストを受信したとき (ビューワーリクエスト)
+ CloudFront がリクエストをオリジンに転送する前 (オリジンリクエスト)
+ CloudFront がオリジンからレスポンスを受信したとき (オリジンレスポンス)
+ CloudFront がビューワーにレスポンスを返す前 (ビューワーレスポンス)

AWS WAF を使用している場合、Lambda@Edge ビューワーリクエストは AWS WAF ルールの適用後に実行されます。

詳細については、「[リクエストとレスポンスを使用する](lambda-generating-http-responses.md)」および「[Lambda@Edge イベント構造](lambda-event-structure.md)」を参照してください。

# Lambda@Edge の使用方法
<a name="lambda-edge-ways-to-use"></a>

Amazon CloudFront ディストリビューションでの Lambda@Edge 処理には多くの用途があります。以下に例を示します。
+ Lambda 関数 は Cookie を検査して URL を書き換え、A/B テスト用に異なるバージョンのサイトをユーザーに表示できます。
+ CloudFront は、デバイスに関する情報が含まれている `User-Agent` ヘッダーを確認し、ビューワーが使用しているデバイスに基づいて、異なるオブジェクトをビューワーに返すことができます。例えば、CloudFront は、デバイスの画面サイズに基づいて異なるイメージを返すことができます。同様に、`Referer` ヘッダーの値を考慮する関数を作成して、CloudFront が最も低い解像度のイメージをボットに返すこともできます。
+ または、他の条件の Cookie を確認できます。例えば、衣料品の通販ウェブサイトで、ユーザーが選択したジャケットの色を Cookie に保存する場合に、Lambda 関数でリクエストを変更して、CloudFront が選択した色のジャケットのイメージを返すようにできます。
+ Lambda 関数は、CloudFront のビューワーリクエストイベントまたはオリジンリクエストイベントの発生時に HTTP レスポンスを生成できます。
+ 関数でヘッダーまたは認可トークンを検査して、CloudFront がリクエストをオリジンに転送する前に、コンテンツへのアクセスを制御するヘッダーを挿入できます。
+ Lambda 関数は、外部リソースのネットワーク呼び出しを実行して、ユーザー認証情報を確認したり、追加のコンテンツを取得してレスポンスをカスタマイズしたりすることもできます。

詳細 (コード例を含む) については、「[Lambda@Edge 関数の例](lambda-examples.md)」を参照してください。

コンソールで Lambda@Edge を設定する方法の詳細については、「[チュートリアル: 基本的な Lambda@Edge 関数 (コンソール) を作成する](lambda-edge-how-it-works-tutorial.md)」を参照してください。

# Lambda@Edge 関数の使用を開始する (コンソール)
<a name="lambda-edge-how-it-works"></a>

Lambda@Edge では、CloudFront トリガーを使用して Lambda 関数を呼び出すことができます。CloudFront ディストリビューションを Lambda 関数に関連付けると、CloudFront エッジロケーションで[リクエストとレスポンスがインターセプト](https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html)され、関数が実行されます。Lambda 関数では、セキュリティを強化したり、ビューワーに近い情報をカスタマイズしてパフォーマンスを向上させたりできます。

次のリストは、CloudFront で Lambda 関数を作成および使用する方法の基本的な概要を示しています。

**概要: CloudFront での Lambda 関数の作成と使用**

1. 米国東部 (バージニア北部) リージョンで Lambda 関数を作成します。

1. 番号付きバージョンの関数を保存して発行します。

   関数を変更する場合、米国東部 (バージニア北部) リージョンで関数の \$1LATEST バージョンを編集する必要があります。次に、CloudFront と連携するように設定する前に、新しい番号付きバージョンを発行します。

1. 関数を CloudFront ディストリビューションとキャッシュ動作に関連付けます。1 つまたは複数の CloudFront イベント (*トリガー*) を指定します。これにより、関数を実行できます。例えば、CloudFront がビューワーからリクエストを受け取ったときに関数を実行させるトリガーを作成できます。

1. トリガーを作成すると、Lambda が世界中の AWS ロケーションに関数のレプリカを作成します。

**ヒント**  
詳細については、「[関数の作成と更新](lambda-edge-create-function.md)」、「[イベント構造](lambda-event-structure.md)」、および「[CloudFront トリガーの追加](lambda-edge-add-triggers.md)」を参照してください。また、さらに多くのアイデアやコードサンプルを「[Lambda@Edge 関数の例](lambda-examples.md)」で参照できます。

ステップバイステップのチュートリアルについては、次のトピックを参照してください。

**Topics**
+ [チュートリアル: 基本的な Lambda@Edge 関数 (コンソール) を作成する](lambda-edge-how-it-works-tutorial.md)

# チュートリアル: 基本的な Lambda@Edge 関数 (コンソール) を作成する
<a name="lambda-edge-how-it-works-tutorial"></a>

このチュートリアルでは、CloudFront で実行される Node.js 関数の例を作成および設定することで、Lambda@Edge の使用を開始する方法を示します。この例では、CloudFront がファイルを取得するときに、セキュリティヘッダーがレスポンスに追加されます。(これにより、ウェブサイトのセキュリティとプライバシーが向上します)。

このチュートリアルでは、独自のウェブサイトは必要ありません。しかしながら、独自の Lambda@Edge ソリューションを作成するときは、同様のステップに従って同じオプションから選択できます。

**Topics**
+ [ステップ 1: AWS アカウント にサインアップする](#lambda-edge-how-it-works-tutorial-AWS)
+ [ステップ 2: CloudFront ディストリビューションを作成する](#lambda-edge-how-it-works-tutorial-cloudfront)
+ [ステップ 3: 関数を作成する](#lambda-edge-how-it-works-tutorial-create-function)
+ [ステップ 4: 関数を実行する CloudFront トリガーを追加する](#lambda-edge-how-it-works-tutorial-add-trigger)
+ [ステップ 5: 関数の実行を確認する](#lambda-edge-how-it-works-tutorial-verify)
+ [ステップ 6: 問題のトラブルシューティングを行う](#lambda-edge-how-it-works-tutorial-troubleshoot)
+ [ステップ 7: リソース例をクリーンアップする](#lambda-edge-how-it-works-tutorial-cleanup-resources)
+ [関連情報](#lambda-edge-how-it-works-tutorial-resources)

## ステップ 1: AWS アカウント にサインアップする
<a name="lambda-edge-how-it-works-tutorial-AWS"></a>

まだサインアップしていない場合は、AWS アカウントにサインアップします。詳細については、「[AWS アカウントへのサインアップ](setting-up-cloudfront.md#sign-up-for-aws)」を参照してください。

## ステップ 2: CloudFront ディストリビューションを作成する
<a name="lambda-edge-how-it-works-tutorial-cloudfront"></a>

Lambda@Edge 関数の例を作成する前に、コンテンツの提供元のオリジンを含む、操作対象の CloudFront 環境が必要です。

この例では、Amazon S3 バケットをディストリビューションのオリジンとして使用する CloudFront ディストリビューションを作成します。使用する環境が既にある場合、このステップは省略できます。<a name="lambda-edge-how-it-works-tutorial-cf-proc"></a>

**Amazon S3 オリジンを使用して CloudFront ディストリビューションを作成するには**

1. サンプルコンテンツ用に、イメージファイルなど 1～2 つのファイルで Amazon S3 バケットを作成します。そのためには、[コンテンツを Amazon S3 にアップロード](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html#GettingStartedUploadContent)するステップに従います。必ず、バケットのオブジェクトへのパブリック読み取りアクセス権を付与するアクセス許可を設定します。

1. CloudFront ウェブディストリビューションを作成するステップに従って、[CloudFront ディストリビューションを作成](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GettingStarted.html#GettingStartedCreateDistribution)し、オリジンとして S3 バケットを追加します。ディストリビューションが既にある場合は、代わりにそのディストリビューションのオリジンとしてバケットを追加できます。
**ヒント**  
ディストリビューション ID をメモします。このチュートリアルで後ほど関数の CloudFront トリガーを追加する場合は、ドロップダウンリストでディストリビューションの ID (`E653W22221KDDL` など) を選択する必要があります。

## ステップ 3: 関数を作成する
<a name="lambda-edge-how-it-works-tutorial-create-function"></a>

このステップでは、Lambda コンソールでブループリントテンプレートから Lambda 関数を作成します。関数コードは、CloudFront ディストリビューションでセキュリティヘッダーを更新するコードを追加します。<a name="lambda-edge-how-it-works-tutorial-create-function-blueprint-proc"></a>

**Lambda 関数を作成するには**

1. AWS マネジメントコンソール にサインインして、AWS Lambda で [https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/) コンソールを開きます。
**重要**  
**US-East-1 (バージニア北部)** AWS リージョン (**us-east-1**) にいることを確認します。Lambda@Edge 関数を作成するには、このリージョンに設定されている必要があります。

1. **[関数を作成]** を選択します。

1. [**関数の作成**] ページで、[**設計図の使用**] を選択し、各フィールドに「**cloudfront**」と入力して CloudFront の設計図をフィルタリングします。
**注記**  
CloudFront の設計図は、**US-East-1 (バージニア北部)** リージョン (**us-east-1**) でのみ使用できます。

1. 関数のテンプレートとして **[HTTP レスポンスヘッダーを変更する]** ブループリントを選択します。

1. 関数に関する次の情報を入力します。
   + **関数名** – 関数の名前を入力します。
   + **実行ロール** – 関数のアクセス許可を設定する方法を選択します。推奨される基本 Lambda@Edge アクセス許可ポリシーテンプレートを使用するには、[**AWS ポリシーテンプレートから新しいロールを作成する**] を選択します。
   + **ロール名** – ポリシーテンプレートで作成するロールの名前を入力します。
   + **ポリシーテンプレート** – 関数の基盤として CloudFront ブループリントを選択したことにより、Lambda は、ポリシーテンプレート **[基本的な Lambda@Edge アクセス許可]** を自動的に追加します。このポリシーテンプレートでは、世界中の CloudFront の場所で、Lambda 関数の実行を CloudFront に許可する実行ロールアクセス許可を追加します。詳細については、「[Lambda@Edge 用の IAM アクセス許可とロールのセットアップ](lambda-edge-permissions.md)」を参照してください。

1. ページの下部で、**[関数を作成]** を選択します。

1. 表示される **[Lambda@Edge へのデプロイ]** ペインで、**[キャンセル]** を選択します (このチュートリアルでは、関数を Lambda@Edge にデプロイする前に関数コードを変更する必要があります)。

1. ページの **[コードソース]** セクションまで下にスクロールします。

1. テンプレートコードを、オリジンが返すセキュリティヘッダーを変更する関数に置き換えます。たとえば、以下のようなコードを実行できます。

   ```
   'use strict';
   export const handler = (event, context, callback) => {
   
       //Get contents of response
       const response = event.Records[0].cf.response;
       const headers = response.headers;
   
       //Set new headers
       headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age= 63072000; includeSubdomains; preload'}];
       headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}];
       headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}];
       headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}];
       headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}];
       headers['referrer-policy'] = [{key: 'Referrer-Policy', value: 'same-origin'}];
   
       //Return modified response
       callback(null, response);
   };
   ```

1. **[ファイル]**、**[保存]** の順に選択して、更新したコードを保存します。

1. **[デプロイ]** をクリックします。

次のセクションに進み、関数を実行する CloudFront トリガーを追加します。

## ステップ 4: 関数を実行する CloudFront トリガーを追加する
<a name="lambda-edge-how-it-works-tutorial-add-trigger"></a>

これでセキュリティヘッダーを更新する Lambda 関数ができたので、CloudFront がディストリビューションのオリジンから受け取ったヘッダーをレスポンスに追加するように、関数を実行する CloudFront トリガーを設定します。<a name="lambda-edge-how-it-works-tutorial-add-trigger-proc"></a>

**関数の CloudFront トリガーを設定するには**

1. Lambda コンソールで、関数の **[関数の概要]** ページの **[トリガーを追加]** を選択します。

1. **[トリガー設定]** で、**[CloudFront]** を選択します。

1. **[Lambda@Edge へのデプロイ]** を選択します。

1. **[Lambda@Edge へのデプロイ]** ペインの **[CloudFront トリガーの設定]** で、次の情報を入力します。
   + **ディストリビューション** – 関数に関連付ける CloudFront ディストリビューション ID。ドロップダウンリストで、ディストリビューション ID を選択します。
   + **キャッシュ動作** – トリガーで使用するキャッシュ動作。この例では、値を **\$1** に設定したままにします。これは、ディストリビューションのデフォルトのキャッシュ動作を意味します。詳細については、「[すべてのディストリビューション設定リファレンス](distribution-web-values-specify.md)」トピックの「[キャッシュ動作の設定](DownloadDistValuesCacheBehavior.md)」を参照してください。
   + **CloudFront イベント** – 関数をいつ実行するか指定するトリガー。CloudFront がオリジンからレスポンスを返すたびに、セキュリティヘッダー関数を実行したいと思います。ドロップダウンリストで **[オリジンレスポンス]** を選択します。詳細については、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。

1. **[Lambda@Edge へのデプロイを確認]** チェックボックスをオンにします。

1. [**デプロイ**] を選択して、トリガーを追加し、世界中の AWS の場所に関数をレプリケートします。

1. 関数がレプリケートするまで待ちます。これには通常数分かかります。

    レプリケーションが終了したかどうかを確認するには、[CloudFront コンソールに移動](https://console.aws.amazon.com/cloudfront/v4/home)し、ディストリビューションを表示します。ディストリビューションのステータスが **[デプロイ中]** から日時に変わるまで待ち、関数がレプリケートされたことを確認します。関数が機能することを確認するには、次のセクションのステップに従います。

## ステップ 5: 関数の実行を確認する
<a name="lambda-edge-how-it-works-tutorial-verify"></a>

Lambda 関数を作成し、CloudFront ディストリビューションに対してその関数を実行するトリガーが設定されたため、関数が正常に動作することを確認します。この例では、CloudFront が返す HTTP ヘッダーで、セキュリティヘッダーが追加されることを確認します。<a name="lambda-edge-how-it-works-tutorial-verify-proc"></a>

**Lambda@Edge 関数でセキュリティヘッダーが追加されることを確認するには**

1. ブラウザで、S3 バケット内のファイルの URL を入力します。たとえば、`https://d111111abcdef8.cloudfront.net/image.jpg` のような URL を使用できます。

   ファイル URL で使用する CloudFront ドメイン名の詳細については、「[CloudFront でファイルの URL 形式をカスタマイズする](LinkFormat.md)」を参照してください。

1. ブラウザのウェブデベロッパーツールバーを開きます。たとえば、Chrome のブラウザウィンドウで、コンテキスト（右クリック）メニューを開き、[**Inspect (調査)**] を選択します。

1. [**Network (ネットワーク)**] タブを選択します。

1. ページを再ロードしてイメージを表示し、左側のペインの HTTP リクエストを選択します。HTTP ヘッダーが別のペインに表示されます。

1. HTTP ヘッダーのリストを確認し、予期されるセキュリティヘッダーがリストに含まれていることを確認します。たとえば、次のスクリーンショットに示すようなヘッダーが表示されます。  
![\[予想されるセキュリティヘッダーがハイライト表示された HTTP ヘッダーのリスト。\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/images/lambda-at-edge-security-headers-list.png)

セキュリティヘッダーがヘッダーのリストに含まれていれば、成功です。最初の Lambda@Edge 関数を正常に作成しました。CloudFront がエラーを返す場合や、その他の問題がある場合は、次のステップに進んで問題のトラブルシューティングを行います。

## ステップ 6: 問題のトラブルシューティングを行う
<a name="lambda-edge-how-it-works-tutorial-troubleshoot"></a>

CloudFront がエラーを返すか、予期どおりにセキュリティヘッダーを追加しない場合は、CloudWatch Logs を参照して関数の実行を調査できます。必ず、関数が実行された場所に最も近い AWS ロケーションで保存されたログを使用します。

例えば、ロンドンからファイルを表示する場合は、CloudWatch コンソールでリージョンを欧州 (ロンドン) に変更してみてください。<a name="lambda-edge-how-it-works-tutorial-cloudwatch-proc"></a>

**Lambda@Edge 関数の CloudWatch Logs を調べるには**

1. AWS マネジメントコンソール にサインインして、CloudWatch コンソール ([https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/)) を開きます。

1. [**リージョン**] を、ブラウザでファイルを表示したときに表示されるロケーションに変更します。これは、関数が実行されている場所です。

1. 左側のペインで、[**ログ**] を選択して、ディストリビューションのログを表示します。

詳細については、「[Amazon CloudWatch で CloudFront メトリクスをモニタリングする](monitoring-using-cloudwatch.md)」を参照してください。

## ステップ 7: リソース例をクリーンアップする
<a name="lambda-edge-how-it-works-tutorial-cleanup-resources"></a>

このチュートリアルのためだけに Amazon S3 バケットと CloudFront ディストリビューションを作成した場合は、割り当てた AWS リソースを削除して、今後料金が発生しないようにしてください。AWS リソースを削除すると、追加したコンテンツは使用できなくなります。

**タスク** 
+ [S3 バケットの削除](#lambda-edge-how-it-works-tutorial-delete-bucket) 
+ [Lambda 関数を削除する](#lambda-edge-how-it-works-tutorial-delete-function)
+ [CloudFront ディストリビューションの削除](#lambda-edge-how-it-works-tutorial-delete-distribution)

### S3 バケットの削除
<a name="lambda-edge-how-it-works-tutorial-delete-bucket"></a>

Amazon S3 バケットを削除する前に、バケットのログ記録が無効であることを確認します。それ以外の場合、削除するバケットへのログの書き込みが AWS によって継続されます。<a name="lambda-edge-how-it-works-tutorial-delete-bucket-proc"></a>

**バケットのログ記録を無効にするには**

1. [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/) で Amazon S3 コンソールを開きます。

1. バケットを選択し、[**プロパティ**] を選択します。

1. [**プロパティ**] から [**ログ記録**] を選択します。

1. [**有効**] チェックボックスをオフにします。

1. [**Save**] を選択します。

これで、バケットを削除できます。詳細については、*Amazon Simple Storage Service コンソールユーザーガイド*の「[バケットの削除](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html)」を参照してください。

### Lambda 関数を削除する
<a name="lambda-edge-how-it-works-tutorial-delete-function"></a>

Lambda 関数の関連付けを削除する手順と、関数自体を削除する手順 (オプション) については、「[Lambda@Edge 関数とレプリカを削除する](lambda-edge-delete-replicas.md)」を参照してください。

### CloudFront ディストリビューションの削除
<a name="lambda-edge-how-it-works-tutorial-delete-distribution"></a>

CloudFront ディストリビューションを削除する前に、ディストリビューションを無効にする必要があります。無効になったディストリビューションは機能しなくなり、料金も発生しません。無効にしたディストリビューションはいつでも有効にすることができます。無効にしたディストリビューションを削除すると、使用できなくなります。<a name="lambda-edge-how-it-works-tutorial-delete-distribution-proc"></a>

**CloudFront ディストリビューションを無効にして削除するには**

1.  で CloudFront コンソールを開きます[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)

1. 無効にするディストリビューションを選択してから [**Disable (無効化)**] を選択します。

1. 確認を求められたら、[**Yes, Disable (はい、無効化する)**] を選択します。

1. 無効にしたディストリビューションを選択してから [**削除**] を選択します。

1. 確認を求めるメッセージが表示されたら、[**Yes, Delete (はい、削除します)**] を選択します。

## 関連情報
<a name="lambda-edge-how-it-works-tutorial-resources"></a>

Lambda@Edge 関数の動作について基本的な理解を得たので、以下を参照してさらに詳しく学習します。
+ [Lambda@Edge 関数の例](lambda-examples.md)
+ [Lambda@Edge 設計のベストプラクティス](https://aws.amazon.com/blogs/networking-and-content-delivery/lambdaedge-design-best-practices/)
+ [Lambda@Edge を使用したレイテンシーの軽減とエッジへのコンピューティングの移行](https://aws.amazon.com/blogs/networking-and-content-delivery/reducing-latency-and-shifting-compute-to-the-edge-with-lambdaedge/)

# Lambda@Edge 用の IAM アクセス許可とロールのセットアップ
<a name="lambda-edge-permissions"></a>

Lambda@Edge を設定するには、AWS Lambda に対する以下の IAM アクセス許可およびロールが必要です。
+ [IAM アクセス許可](#lambda-edge-permissions-required) – これらのアクセス許可により、Lambda 関数を作成して CloudFront ディストリビューションに関連付けることができます。
+ [Lambda 関数実行ロール](#lambda-edge-permissions-function-execution) (IAM ロール) – Lambda サービスプリンシパルは、このロールを引き受けて関数を実行します。
+ [Lambda@Edge のサービスリンクロール](#using-service-linked-roles-lambda-edge) – サービスリンクロールにより、特定の AWS のサービス が Lambda 関数を AWS リージョン にレプリケートし、CloudWatch が CloudFront ログファイルを使用できるようになります。

## Lambda@Edge 関数を CloudFront ディストリビューションに関連付けるために必要な IAM アクセス許可
<a name="lambda-edge-permissions-required"></a>

Lambda に必要な IAM アクセス許可に加え、ユーザーは、Lambda 関数を CloudFront ディストリビューションに関連付けるための以下の IAM アクセス許可が必要です。
+ `lambda:GetFunction` – Lambda 関数の設定情報を取得するためのアクセス許可、およびその関数を含む `.zip` ファイルをダウンロードするための署名付き URL を取得するアクセス許可を付与します。
+ `lambda:EnableReplication*` – Lambda レプリケーションサービスが関数コードと設定を取得するためのアクセス許可をリソースポリシーに付与します。
+ `lambda:DisableReplication*` – Lambda レプリケーションサービスが関数を削除するためのアクセス許可をリソースポリシーに付与します。
**重要**  
`lambda:EnableReplication*` および `lambda:DisableReplication*` アクションの最後にアスタリスク (`*`) を追加する必要があります。
+ リソースに対して、次の例のように、CloudFront イベントが発生した場合に実行する関数バージョンの ARN を指定します。

  `arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2`
+ `iam:CreateServiceLinkedRole` – Lambda@Edge が CloudFront で Lambda 関数をレプリケートするために使用するサービスリンクロールを作成するアクセス許可を付与します。Lambda@Edge を初めて設定すると、サービスリンクロールが自動的に作成されます。Lambda@Edge を使用する他のディストリビューションにこのアクセス許可を追加する必要はありません。

  
+ `cloudfront:UpdateDistribution` または `cloudfront:CreateDistribution` – ディストリビューションを更新または作成するアクセス許可を付与します。

詳細については、以下の各トピックを参照してください。
+ [Amazon CloudFront のアイデンティティとアクセス管理](security-iam.md)
+ 「*AWS Lambda デベロッパーガイド*」の「[Lambda リソースのアクセス許可](https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role)」

## サービスプリンシパルの関数実行ロール
<a name="lambda-edge-permissions-function-execution"></a>

ユーザーの関数を実行するときに `lambda.amazonaws.com` と `edgelambda.amazonaws.com` サービスプリンシパル が引き受けることができる IAM ロールを作成する必要があります。

**ヒント**  
Lambda コンソールで関数を作成する場合、AWS ポリシーテンプレートを使用して新しい実行ロールを作成することを選択できます。このステップでは、関数を実行するために必要な Lambda@Edge アクセス許可が*自動的に*追加されます。[チュートリアル: シンプルな Lambda@Edge 関数の作成のステップ 5](lambda-edge-how-it-works-tutorial.md#lambda-edge-how-it-works-tutorial-create-function) を参照してください。

IAM ロールを手動で作成する詳細については、「*IAM ユーザーガイド*」の「[ロールの作成とポリシーのアタッチ (コンソール)](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_job-functions_create-policies.html)」を参照してください。

**Example 例: ロール信頼ポリシー**  
IAM コンソールの **[信頼関係]** タブで、このロールを追加できます。このポリシーは **[アクセス許可]** タブには追加しないでください。    
****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "Service": [
               "lambda.amazonaws.com",
               "edgelambda.amazonaws.com"
            ]
         },
         "Action": "sts:AssumeRole"
      }
   ]
}
```

実行ロールに付与する必要がある許可の詳細については、「*AWS Lambda デベロッパーガイド*」の「[Lambda リソースのアクセス許可](https://docs.aws.amazon.com/lambda/latest/dg/intro-permission-model.html#lambda-intro-execution-role)」を参照してください。

**注意事項**  
デフォルトでは、CloudFront イベントが Lambda 関数をトリガーするたびに、データが CloudWatch Logs に書き込まれます。これらのログを使用する場合は、CloudWatch Logs にデータを書き込むためのアクセス権限が実行ロールに必要です。事前定義された AWSLambdaBasicExecutionRole を使用して、実行ロールにアクセス許可を付与できます。  
CloudWatch Logs の詳細については、「[エッジ関数のログ](edge-functions-logs.md)」を参照してください。
S3 バケットからのオブジェクトの読み取りなど、Lambda 関数コードが他の AWS リソースにアクセスする場合、そのアクションを実行するためのアクセス許可が実行ロールに必要です。

## Lambda@Edge 用のサービスにリンクされたロール
<a name="using-service-linked-roles-lambda-edge"></a>

Lambda@Edge は IAM [サービスリンクロール](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-service-linked-role)を使用します。サービスにリンクされたロールは、サービスに直接リンクされた一意のタイプの IAM ロールです。サービスにリンクされたロールは、サービスによって事前定義されており、お客様の代わりにサービスから他の AWS サービスを呼び出す必要のあるアクセス許可がすべて含まれています。

Lambda@Edge は、以下の IAM サービスリンクロールを使用します。
+ **AWSServiceRoleForLambdaReplicator** - Lambda@Edge はこのロールを使用して、Lambda@Edge が関数を AWS リージョン にレプリケートできるようにします。

  CloudFront で Lambda@Edge トリガーを初めて追加すると、AWSServiceRoleForLambdaReplicator という名前のロールが自動的に作成され、Lambda@Edge が関数を AWS リージョン にレプリケートできるようになります。このロールは、Lambda@Edge 関数を使用するために必要です。AWSServiceRoleForLambdaReplicator ロールの ARN は次の例のようになります。

  `arn:aws:iam::123456789012:role/aws-service-role/replicator.lambda.amazonaws.com/AWSServiceRoleForLambdaReplicator`
+ **AWSServiceRoleForCloudFrontLogger** – CloudFront はこのロールを使用してログファイルを CloudWatch にプッシュします。ログファイルを使用して Lambda@Edge 検証エラーをデバッグできます。

  Lambda@Edge 関数の関連付けを追加すると、AWSServiceRoleForCloudFrontLogger ロールが自動的に作成され、CloudFront が Lambda@Edge エラーログファイルを CloudWatch にプッシュできるようになります。AWSServiceRoleForCloudFrontLogger の ARN は次のようになります。

  `arn:aws:iam::account_number:role/aws-service-role/logger.cloudfront.amazonaws.com/AWSServiceRoleForCloudFrontLogger`

サービスリンクロールを使用することで、必要なアクセス許可を手動で追加する必要がなくなるため、Lambda@Edge のセットアップと使用が簡単になります。Lambda@Edge はそのサービスリンクロールのアクセス許可を定義し、Lambda@Edge のみがそのロールを引き受けることができます。定義されたアクセス権限には、信頼ポリシーとアクセス権限ポリシーが含まれます。その他の IAM エンティティにアクセス許可ポリシーをアタッチすることはできません。

サービスにリンクされたロールを削除するには、その前に、それらのロールに関連付けられている CloudFront または Lambda@Edge のリソースを削除する必要があります。このようにして、アクティブなリソースにアクセスするためにまだ必要な、サービスリンクロールを削除しないようにすることで、Lambda@Edge リソースが保護されます。

サービスにリンクされたロールの詳細については、「[CloudFront のサービスにリンクされたロール](security_iam_service-with-iam.md#security_iam_service-with-iam-roles-service-linked)」を参照してください。

### Lambda@Edge 用のサービスにリンクされたロールのアクセス許可
<a name="slr-permissions-lambda-edge"></a>

Lambda@Edge は、**AWSServiceRoleForLambdaReplicator** および **AWSServiceRoleForCloudFrontLogger** という名前の 2 つのサービスにリンクされたロールを使用します。以下のセクションでは、それらの各ロールのアクセス許可を管理する方法について説明します。

**Contents**
+ [Lambda Replicator 用のサービスにリンクされたロールのアクセス許可](#slr-permissions-lambda-replicator)
+ [CloudFront ロガー用のサービスにリンクされたロールのアクセス許可](#slr-permissions-cloudfront-logger)

#### Lambda Replicator 用のサービスにリンクされたロールのアクセス許可
<a name="slr-permissions-lambda-replicator"></a>

このサービスにリンクされたロールにより、Lambda が Lambda@Edge 関数を AWS リージョン にレプリケートできるようになります。

AWSServiceRoleForLambdaReplicator サービスにリンクされたロールは、ロールを継承するために `replicator.lambda.amazonaws.com` のサービスを信頼します。

このロールのアクセス権限ポリシーは、Lambda@Edge が以下のアクションを指定されたリソースに対して実行することを許可します。
+ `lambda:CreateFunction` の。`arn:aws:lambda:*:*:function:*`
+ `lambda:DeleteFunction` の。`arn:aws:lambda:*:*:function:*`
+ `lambda:DisableReplication` の。`arn:aws:lambda:*:*:function:*`
+ `iam:PassRole` の。`all AWS resources`
+  `cloudfront:ListDistributionsByLambdaFunction` の。`all AWS resources`

#### CloudFront ロガー用のサービスにリンクされたロールのアクセス許可
<a name="slr-permissions-cloudfront-logger"></a>

このサービスリンクロールでは、Lambda@Edge の検証エラーをデバッグするのに役立つように CloudFront が CloudWatch にログファイルをプッシュすることが許可されます。

AWSServiceRoleForCloudFrontLogger サービスにリンクされたロールは、ロールを継承するために `logger.cloudfront.amazonaws.com` のサービスを信頼します。

このロールのアクセス権限ポリシーは、Lambda@Edge が以下のアクションを指定された `arn:aws:logs:*:*:log-group:/aws/cloudfront/*` リソースに対して実行することを許可します。
+ `logs:CreateLogGroup` ``
+ `logs:CreateLogStream`
+ `logs:PutLogEvents`

IAM エンティティ (ユーザー、グループ、ロールなど) で Lambda@Edge のサービスにリンクされたロールを削除できるように、アクセス許可を設定する必要があります。詳細については*IAM ユーザーガイド* の「[サービスにリンクされた役割のアクセス許可](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html#service-linked-role-permissions)」を参照してください。

### Lambda@Edge 用のサービスにリンクされたロールの作成
<a name="create-slr-lambda-edge"></a>

通常、Lambda@Edge のサービスにリンクされたロールを手動で作成することはありません。以下のシナリオで、サービスによってロールが自動的に作成されます。
+ トリガーを初めて作成するとき、サービスは AWSServiceRoleForLambdaReplicator ロールを作成します (まだ存在しない場合）。このロールにより、Lambda が Lambda@Edge 関数を AWS リージョン にレプリケートできるようになります。

  このサービスにリンクされたロールを削除した場合、Lambda@Edge の新しいトリガーをディストリビューションに追加すると、そのロールは再び作成されます。
+ Lambda@Edge が関連付けられた CloudFront ディストリビューションを更新または作成すると、サービスによって AWSServiceRoleForCloudFrontLogger ロールが作成されます (まだ存在しない場合)。このロールにより、CloudFront が CloudWatch にログファイルをプッシュできるようになります。

  このサービスリンクロールを削除した場合は、Lambda@Edge の関連付けがある CloudFront ディストリビューションを更新または作成すると、そのロールが再び作成されます。

これらのサービスリンクロールを手動で作成する必要がある場合は、次の AWS Command Line Interface (AWS CLI) コマンドを実行します。

**AWSServiceRoleForLambdaReplicator ロールを作成するには**
+ 以下のコマンドを実行してください。

  ```
  aws iam create-service-linked-role --aws-service-name replicator.lambda.amazonaws.com
  ```

**AWSServiceRoleForCloudFrontLogger ロールを作成するには**
+ 以下のコマンドを実行してください。

  ```
  aws iam create-service-linked-role --aws-service-name logger.cloudfront.amazonaws.com
  ```

### Lambda@Edge のサービスにリンクされたロールの編集
<a name="edit-slr-lambda-edge"></a>

Lambda@Edge のサービスリンクロール AWSServiceRoleForLambdaReplicator または AWSServiceRoleForCloudFrontLogger を編集することはできません。サービスによってサービスリンクロールが作成された後は、多くのエンティティでそのロールが参照されるため、そのロール名は変更できません。ただし、IAM を使用してロールの説明を編集することはできます。詳細については、「*IAM ユーザーガイド*」の「[サービスリンクロールの編集](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html#edit-service-linked-role)」を参照してください。

### Lambda@Edge サービスリンクロールでサポートされている AWS リージョン
<a name="slr-regions-lambda-edge"></a>

CloudFront は、次の AWS リージョン で Lambda@Edge 用のサービスにリンクされたロールの使用をサポートしています。
+ 米国東部 (バージニア北部) – `us-east-1`
+ 米国東部 (オハイオ) – `us-east-2`
+ 米国西部 (北カリフォルニア) – `us-west-1`
+ 米国西部 (オレゴン) – `us-west-2`
+ アジアパシフィック (ムンバイ) – `ap-south-1`
+ アジアパシフィック (ソウル) – `ap-northeast-2`
+ アジアパシフィック (シンガポール) – `ap-southeast-1`
+ アジアパシフィック (シドニー) – `ap-southeast-2`
+ アジアパシフィック (東京) – `ap-northeast-1`
+ 欧州 (フランクフルト) – `eu-central-1`
+ 欧州 (アイルランド) – `eu-west-1`
+ 欧州 (ロンドン) – `eu-west-2`
+ 南米 (サンパウロ) – `sa-east-1`

# Lambda@Edge 関数を記述および作成する
<a name="lambda-edge-create-function"></a>

Lambda@Edge を使用するには、AWS Lambda 関数のコードを*記述*します。Lambda@Edge 関数の記述については、以下のリソースを参照してください。
+  [Lambda@Edge イベント構造](lambda-event-structure.md) – Lambda@Edge で使用するイベント構造を理解します。
+ [Lambda@Edge 関数の例](lambda-examples.md) – A/B テストや HTTP リダイレクトの生成などの関数の例。

Lambda@Edge で Node.js または Python を使用するためのプログラミングモデルは、AWS リージョン で Lambda を使用するプログラミングモデルと同じです。詳細については、「*AWS Lambda デベロッパーガイド*」の「[Node.js を使用した Lambda 関数の作成](https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html)」または「[Python を使用した Lambda 関数の作成](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html)」を参照してください。

Lambda@Edge 関数で、`callback` パラメータを含めて、リクエストまたはレスポンスイベントの該当するオブジェクトを返します。
+ **リクエストイベント** - レスポンスに `cf.request` オブジェクトを含めます。

  レスポンスを生成している場合は、レスポンスに `cf.response` オブジェクトを含めます。詳細については、「[リクエストトリガーでの HTTP レスポンスを生成する](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests)」を参照してください。
+ **レスポンスイベント** - レスポンスに `cf.response` オブジェクトを含めます。

独自のコードを記述するか、いずれかの例を使用した後で、Lambda で関数を作成します。関数を作成したり、既存の関数を編集したりするには、以下のトピックを参照してください。

**Topics**
+ [Lambda@Edge 関数を作成する](lambda-edge-create-in-lambda-console.md)
+ [Lambda 関数を編集する](lambda-edge-edit-function.md)

 Lambda で関数を作成したら、トリガーと呼ばれる特定の CloudFront イベントに基づいて関数を実行するように Lambda を設定します。**詳細については、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。

# Lambda@Edge 関数を作成する
<a name="lambda-edge-create-in-lambda-console"></a>

CloudFront イベントに基づく Lambda 関数を実行するように AWS Lambda をセットアップするには、この手順を実行します。<a name="lambda-edge-create-function-procedure"></a>

**ターゲットの Lambda@Edge 関数を作成するには**

1. AWS マネジメントコンソール にサインインして AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) を開きます。

1. 1 つ以上の Lambda 関数が既にある場合は、[**Create function**] を選択します。

   関数がない場合は、[**Get Started Now**] を選択します。

1. ページの上部にあるリージョンのリストで、[**米国東部 (バージニア北部)**] を選択します。

1. 独自のコードを使用して関数を作成するか、CloudFront の設計図で始まる関数を作成します。
   + 独自のコードを使用して関数を作成するには、[**Author from scratch**] を選択します。
   + CloudFront のブループリントを一覧表示するには、フィルタフィールドに「**cloudfront**」と入力し、**Enter** キーを選択します。

     使用するブループリントを見つけたら、ブループリントの名前を選択します｡

1. **[基本情報]** セクションで、以下の値を指定します。

   1. **名前** - 関数の名前を入力します。

   1. **ロール** – すぐに開始するには、**[テンプレートから新しいロールを作成する複数]** を選択します。**[既存のロールを選択]** または **[カスタムロールを作成]** を選択し、プロンプトに従ってこのセクションの情報を完了することもできます。

   1. **ロール名** - ロールの名前を入力します。

   1. **ポリシーテンプレート** – **[基本的な Edge Lambda のアクセス許可]** を選択します。

1. ステップ 4 で [**Author from scratch**] を選択した場合は、ステップ 7 に進んでください。

   ステップ 4 で設計図を選択した場合は、[**cloudfront**] セクションで、この関数を CloudFront ディストリビューションおよび CloudFront イベントのキャッシュに関連付ける 1 つのトリガーを作成できます。この時点で [**Remove**] を選択することをお勧めします。そのため、関数の作成時にトリガーはありません。後でトリガーを追加できます。
**ヒント**  
トリガーを追加する前に、関数をテストおよびデバッグすることをお勧めします。代わりにトリガーを追加する場合、関数を作成するとすぐに関数が実行され、世界各地の AWS ロケーションへのレプリケーションが完了し、対応するディストリビューションがデプロイされます。

1. [**関数の作成**] を選択します。

   Lambda は関数 \$1LATEST とバージョン 1 の 2 つのバージョンを作成します。\$1LATEST バージョンのみを編集できますが、コンソールに最初はバージョン 1 が表示されます。

1. 関数を編集するには、関数の ARN の下にあるページの上部にある [**Version 1**] を選択します。次に [**Versions**] タブで [**\$1LATEST**] を選択します。(その関数をそのままにしてから戻った場合、ボタンラベルは [**Qualifiers**] となります)。

1. [**Configuration**] タブで、該当する [**Code entry type**] を選択します。次に、プロンプトに従ってコードを編集またはアップロードします。

1. [**ランタイム**] で、関数のコードに基づいて値を選択します。

1. [**Tags**] セクションで、該当するタグを追加します。

1. [**Actions**] を選択し、[**Publish new version**] を選択します。

1. 新しいバージョンの関数に関する説明を入力します。

1. [**Publish**] を選択します。

1. 関数をテストおよびデバッグします。Lambda コンソールでのテストの詳細については、「AWS Lambda 開発者ガイド」の「[コンソールを使用して Lambda 関数を呼び出す](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually)」を参照してください。**

1. CloudFront イベントに対して関数を実行する準備ができたら、別のバージョンを公開し、トリガーを追加する関数を編集します。詳細については、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。

# Lambda 関数を編集する
<a name="lambda-edge-edit-function"></a>

Lambda@Edge 関数を作成したら、Lambda コンソールを使用して関数を編集できます。

**注意事項**  
元のバージョンのラベルは [\$1LATEST] です。
\$1LATEST バージョンのみを編集できます。
\$1LATEST バージョンを編集するたびに、新しい番号付きバージョンを公開する必要があります。
\$1LATEST のトリガーを作成することはできません。
新しいバージョンの関数を発行する場合、Lambda は以前のバージョンから新しいバージョンにトリガーを自動的にコピーしません。新しいバージョン用のトリガーを再現する必要があります。
CloudFront イベントのトリガーを関数に追加する場合、同じディストリビューション、キャッシュ動作、および同じ関数の以前のバージョン用のイベント用のトリガーが既に存在している場合、Lambda は以前のバージョンからトリガーを削除します。
トリガーを追加するなど、CloudFront ディストリビューションを更新した後で、トリガーで指定した関数が機能する前に、変更がエッジロケーションに伝達されるのを待つ必要があります。<a name="lambda-edge-edit-function-procedure"></a>

**Lambda 関数を編集するには**

1. AWS マネジメントコンソール にサインインして AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) を開きます。

1. ページの上部にあるリージョンのリストで、[**米国東部 (バージニア北部)**] を選択します。

1. 関数のリストで、関数の名前を選択します。

   デフォルトでは、\$1LATEST バージョンがコンソールに表示されます。以前のバージョンを表示することはできますが ([**Qualifiers**] を選択します)、編集できるのは \$1LATEST のみです。

1. [**Code (コード)**] タブの [**Code entry type (コードの入力タイプ)**] で、ブラウザでのコードの編集、.zip ファイルのアップロード、または Amazon S3 からのファイルのアップロードを選択します。

1. [**Save**] または [**Save and test**] を選択します。

1. [**Actions**] を選択し、[**Publish new version**] を選択します。

1. [**Publish new version from \$1LATEST**] ダイアログボックスで、新しいバージョンの説明を入力します。この説明は、自動的に生成されたバージョン番号とともにバージョンのリストに表示されます。

1. [**Publish**] を選択します。

   新しいバージョンが自動的に最新バージョンになります。バージョン番号はページの左上隅にある **[バージョン]**に表示されます。
**注記**  
関数のトリガーをまだ追加していない場合は、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。

1. [**Triggers**] タブを選択します。

1. [**Add trigger**] を選択します。

1. [**Add trigger (トリガーの追加)**] ダイアログボックスでチェックボックスをオンにし、[**CloudFront**] を選択します。
**注記**  
関数の 1 つまたは複数のトリガーを作成済みの場合、CloudFront がデフォルトのサービスになります。

1. Lambda 関数をいつ実行するかを示す、次の値を指定します。

   1. **ディストリビューション ID **– トリガーの追加先となるディストリビューションの ID を選択します。

   1. **キャッシュ動作** – 関数を実行するオブジェクトを指定するキャッシュ動作を選択します。

   1. **CloudFront イベント** – 関数を実行させる CloudFront イベントを選択します。

   1. **Enable trigger and replicate** – このチェックボックスをオンにし、Lambda が関数を AWS リージョン に対してグローバルにレプリケートするようにします。

1. **[送信]** を選択します。

1. この関数のトリガーをさらに追加するには、ステップ 10～13 を繰り返します。

Lambda コンソールで関数をテストおよびデバッグする方法の詳細については、「AWS Lambda 開発者ガイド」の「[コンソールを使用して Lambda 関数を呼び出す](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually)」を参照してください。**

CloudFront イベントに対して関数を実行する準備ができたら、別のバージョンを公開し、トリガーを追加する関数を編集します。詳細については、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。

# Lambda@Edge 関数のトリガーを追加する
<a name="lambda-edge-add-triggers"></a>

Lambda@Edge トリガーは、CloudFront ディストリビューション、キャッシュ動作、および関数を実行させるイベントの 1 つの組み合わせです。例えば、ディストリビューション用に設定した特定のキャッシュ動作について、CloudFront がビューワーからリクエストを受け取ったときに関数を実行させるトリガーを作成できます。1 つ以上の CloudFront トリガーを指定できます。

**ヒント**  
CloudFront ディストリビューションを作成するときは、別のリクエストを受け取ったときに応答する方法を CloudFront に指示する設定を指定します。デフォルトの設定は、ディストリビューションの*デフォルトのキャッシュ動作*と呼ばれます。特定のファイルタイプのリクエストを受け取る場合など、特定の状況での CloudFront の応答方法を定義する追加のキャッシュ動作を設定できます。詳細については、「[キャッシュ動作の設定](DownloadDistValuesCacheBehavior.md)」を参照してください。

Lambda 関数を最初に作成するときは、1 つのトリガーのみを指定できます。**Lambda コンソールを使用するか、CloudFront コンソールでディストリビューションを編集するかで、後で同じ関数にさらにトリガーを追加できます。
+ Lambda コンソールは、同じ CloudFront ディストリビューションの関数にトリガーを追加する場合に適しています。
+ 更新するディストリビューションを見つけやすいため、複数のディストリビューションのトリガーを追加する場合は、CloudFront コンソールが適しています。同時に他の CloudFront 設定を更新することもできます。

**Topics**
+ [Lambda@Edge 関数をトリガーできる CloudFront イベント](lambda-cloudfront-trigger-events.md)
+ [イベントを選択して関数をトリガーする](lambda-how-to-choose-event.md)
+ [Lambda@Edge 関数にトリガーを追加する (コンソール)](lambda-edge-add-triggers-console.md)

# Lambda@Edge 関数をトリガーできる CloudFront イベント
<a name="lambda-cloudfront-trigger-events"></a>

Amazon CloudFront ディストリビューションの各キャッシュ動作に、特定の CloudFront イベントの発生時に Lambda 関数を実行させるトリガー (関連付け) を 4 つまで追加できます。CloudFront トリガーは、次の図に示す、4 つの CloudFront イベントのいずれかに基づくことができます。

![\[Lambda 関数の CloudFront トリガーイベントが CloudFront と統合する仕組みを示す概念的なグラフィック。\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/images/cloudfront-events-that-trigger-lambda-functions.png)


Lambda@Edge 関数のトリガーに使用できる CloudFront イベントには、以下のものがあります。

**ビューワーリクエスト**  
CloudFront がビューワーからリクエストを受け取ると、リクエストされたオブジェクトが CloudFront キャッシュにあるかどうかを確認する前に関数が実行されます。  
次の場合には関数は実行されません。  
+ カスタムエラーページを取得する場合。
+ CloudFront で HTTP リクエストが自動的に HTTPS にリダイレクトされる場合 ([[ビューワープロトコルポリシー](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)] の値が **[Redirect HTTP to HTTPS]** の場合)

**オリジンリクエスト**  
CloudFront がリクエストをオリジンに転送したときに*のみ*、関数が実行されます。リクエストされたオブジェクトが CloudFront キャッシュ内にある場合、関数は実行されません。

**オリジンレスポンス**  
CloudFront がオリジンからのレスポンスを受け取った後、レスポンス内のオブジェクトをキャッシュする前に関数が実行されます。関数は、オリジンからエラーが返された場合でも実行されることに注意してください。  
次の場合には関数は実行されません。  
+ リクエストされたファイルが CloudFront キャッシュ内にあり、その有効期限が切れていない場合。
+ オリジンリクエストイベントによってトリガーされた関数からレスポンスが生成された場合。

**ビューワーレスポンス**  
リクエストされたファイルがビューワーに返される前に関数が実行されます。ファイルが CloudFront キャッシュ内に既に存在するかどうかに関係なく、関数が実行されることに注意してください。  
次の場合には関数は実行されません。  
+ オリジンが HTTP ステータスコードとして 400 以上を返した場合。
+ カスタムエラーページが返された場合。
+ ビューワーリクエストイベントによってトリガーされた関数からレスポンスが生成された場合。
+ CloudFront で HTTP リクエストが自動的に HTTPS にリダイレクトされる場合 ([[ビューワープロトコルポリシー](DownloadDistValuesCacheBehavior.md#DownloadDistValuesViewerProtocolPolicy)] の値が [**Redirect HTTP to HTTPS**] の場合)

同じキャッシュ動作に複数のトリガーを追加する場合、各トリガーに対して同じ関数を実行することも、異なる関数を実行することもできます。また、複数のディストリビューションに同じ関数を関連付けることもできます。

**注記**  
CloudFront イベントが Lambda 関数の実行をトリガーすると、その関数が終了するまで CloudFront は続行できません。**  
例えば、CloudFront ビューワーリクエストイベントによって Lambda 関数がトリガーされると、その Lambda 関数が実行を終了するまで、CloudFront からビューワーにレスポンスは返されず、リクエストはオリジンに転送されません。  
つまり、Lambda 関数をトリガーするリクエストごとにリクエストのレイテンシーが長くなるため、関数をできるだけ速く実行する必要があります。

# イベントを選択して関数をトリガーする
<a name="lambda-how-to-choose-event"></a>

Lambda 関数をトリガーするために使用する CloudFront イベントを決定する際には、次の点を考慮してください。

**Lambda 関数によって変更されたオブジェクトを CloudFront でキャッシュする場合**  
Lambda 関数によって変更されたオブジェクトを CloudFront でキャッシュして、そのオブジェクトが次回にリクエストされたときにエッジロケーションから提供できるようにする場合は、オリジンリクエストイベントまたはオリジンレスポンスイベントを使用します。****  
これにより、オリジンの負荷と以降のリクエストのレイテンシーが軽減され、以降のリクエストで Lambda@Edge を呼び出すコストが削減されます。  
例えば、オリジンから返されたオブジェクトのヘッダーを追加、削除、または変更する場合に、その結果を CloudFront でキャッシュするには、オリジンレスポンスイベントを使用します。

**すべてのリクエストに対して関数を実行する場合**  
CloudFront が受信したディストリビューションのすべてのリクエストに対して関数を実行する場合は、ビューワーリクエストイベントまたはビューワーレスポンスイベントを使用します。****  
オリジンリクエストイベントとオリジンレスポンスイベントは、リクエストされたオブジェクトがエッジロケーションにキャッシュされておらず、CloudFront がリクエストをオリジンに転送する場合にだけ発生します。

**関数でキャッシュキーを変更する場合**  
キャッシュの基準として使用している値を変更する場合は、ビューワーリクエストイベントを使用します。**  
たとえば、関数で URL を変更してパスに言語の省略形を含める場合 (ユーザーがドロップダウンリストから言語を選択した場合など) は、ビューワーリクエストイベントを使用します。  
+ **ビューワーリクエストの URL** - https://example.com/en/index.html
+ **リクエストがドイツの IP アドレスから送られてきた場合の URL** - https://example.com/de/index.html
Cookie またはリクエストヘッダーをキャッシュ条件として使用している場合もビューワーリクエストイベントを使用します。  
関数で Cookie またはヘッダーを変更する場合は、リクエストの該当部分をオリジンに転送するように CloudFront を設定します。詳細については、以下の各トピックを参照してください。  
+ [Cookie に基づいてコンテンツをキャッシュする](Cookies.md)
+ [リクエストヘッダーに基づいてコンテンツをキャッシュする](header-caching.md)

**関数がオリジンからのレスポンスに影響を与える**  
オリジンからのレスポンスに影響を与えるような方法でリクエストを変更するには、オリジンリクエストイベントを使用します。**  
通常、ほとんどのビューワーリクエストイベントはオリジンに転送されません。CloudFront は、エッジキャッシュに既に存在するオブジェクトを使用してリクエストに応答します。オリジンリクエストイベントに基づく関数でリクエストを変更すると、変更されたオリジンリクエストに対するレスポンスが CloudFront でキャッシュされます。

# Lambda@Edge 関数にトリガーを追加する (コンソール)
<a name="lambda-edge-add-triggers-console"></a>

AWS Lambda コンソールまたは Amazon CloudFront コンソールのいずれかを使用して、Lambda@Edge 関数のトリガーを追加できます。

**重要**  
トリガーは、関数の番号付きバージョン (**\$1LATEST** ではなく) に対してのみ作成できます。

------
#### [ Lambda console ]<a name="lambda-edge-add-triggers-procedure"></a>

**CloudFront イベントのトリガーを Lambda@Edge 関数に追加するには**

1. AWS マネジメントコンソール にサインインして AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) を開きます。

1. ページの上部にあるリージョンのリストで、[**米国東部 (バージニア北部)**] を選択します。

1. [**Functions**] ページで、トリガーを追加する関数の名前を選択します。

1. **[関数の概要]** ページで、**[バージョン]** タブを選択します。

1. トリガーを追加するバージョンを選択します。

   バージョンを選択すると、ボタンの名前が [**Version: \$1LATEST**] または [**Version:*** バージョン番号*] に変わります。

1. [**Triggers**] タブを選択します。

1. [**Add trigger**] を選択します。

1. **[トリガー設定]** で、**[ソースを選択]** を選択し、**cloudfront** と入力し、**CloudFront** を選択します。
**注記**  
1 つまたは複数のトリガーを作成済みの場合、CloudFront がデフォルトのサービスになります。

1. Lambda 関数をいつ実行するかを示す、次の値を指定します。

   1. **ディストリビューション** – トリガーを追加するディストリビューションを選択します。

   1. **キャッシュ動作** – 関数を実行するオブジェクトを指定するキャッシュ動作を選択します。
**注記**  
キャッシュ動作に `*` を指定すると、Lambda 関数はデフォルトのキャッシュ動作にデプロイされます。

   1. **CloudFront イベント** – 関数を実行させる CloudFront イベントを選択します。

   1. **本文を含める** – 関数のリクエストボディにアクセスするには、このチェックボックスをオンにします。

   1. **Lambda@Edge へのデプロイを確認** – このチェックボックスをオンにして、AWS Lambda が関数を AWS リージョン にグローバルにレプリケートするようにします。

1. **[Add]** (追加) を選択します。

   この関数は、更新された CloudFront ディストリビューションがデプロイされたときに、指定された CloudFront イベントのリクエストの処理を開始します。ディストリビューションがデプロイされているかどうかを確認するには、ナビゲーションペインで [**Distributions**] を選択します。ディストリビューションをデプロイすると、ディストリビューションの **[ステータス]** 列の値が、**[デプロイ中]** からデプロイの日時に変わります。

------
#### [ CloudFront console ]<a name="lambda-create-functions-add-triggers-cloudfront-console-procedure"></a>

**CloudFront イベントのトリガーを Lambda@Edge 関数に追加するには**

1. トリガーを追加する Lambda 関数の ARN を取得します。

   1. AWS マネジメントコンソール にサインインして AWS Lambda コンソール ([https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)) を開きます。

   1. ページの上部にあるリージョンのリストで、[**米国東部 (バージニア北部)**] を選択します。

   1. 関数のリストで、トリガーを追加する関数の名前を選択します。

   1. **[関数の概要]** ページで **[バージョン]** タブを選択し、トリガーを追加する先の番号付きバージョンを選択します。

   1. **[ARN をコピー]** ボタンを選択して、ARN をクリップボードにコピーします。Lambda 関数の ARN は次のようになります。

      `arn:aws:lambda:us-east-1:123456789012:function:TestFunction:2`

      末尾の番号 (この例では **2**) は関数のバージョン番号です。

1.  で CloudFront コンソールを開きます[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)

1. ディストリビューションのリストで、トリガーを追加するディストリビューションの ID を選択します。

1. [**Behaviors**] タブを選択します。

1. トリガーを追加する先のキャッシュ動作を選択し、**[編集]** を選択します。

1. **[関数の関連付け]** で、**[関数タイプ]** リストから **[Lambda@Edge]** を選択し、ビューワーリクエスト、ビューワーレスポンス、オリジンリクエスト、またはオリジンレスポンスに対して関数をいつ実行するかを選択します。

   詳細については、「[イベントを選択して関数をトリガーする](lambda-how-to-choose-event.md)」を参照してください。

1. **[関数 ARN/名前]** テキストボックスに、選択したイベントの発生時に実行する Lambda 関数の ARN を貼り付けます。これは Lambda コンソールからコピーした値です。

1. 関数のリクエスト本文にアクセスする場合は、**[本文を含める]** を選択します。

   リクエスト本文を置き換えるだけの場合は、このオプションを選択する必要はありません。

1. 他のイベントタイプで同じ関数を実行するには、ステップ 6 と 7 を繰り返します。

1. **[Save changes]** (変更の保存) をクリックします。

1. このディストリビューションの他のキャッシュ動作にトリガーを追加するには、ステップ 5～10 を繰り返します。

   この関数は、更新された CloudFront ディストリビューションがデプロイされたときに、指定された CloudFront イベントのリクエストの処理を開始します。ディストリビューションがデプロイされているかどうかを確認するには、ナビゲーションペインで [**Distributions**] を選択します。ディストリビューションをデプロイすると、ディストリビューションの **[ステータス]** 列の値が、**[デプロイ中]** からデプロイの日時に変わります。

------

# Lambda@Edge 関数をテストおよびデバッグする
<a name="lambda-edge-testing-debugging"></a>

Lambda@Edge 関数コードのスタンドアロンをテストすること、目的のタスクの完了を確認すること、統合のテストを行うこと、CloudFront で関数が正しく機能しているか確認することは重要です。

統合テスト中または関数がデプロイされた後に、HTTP 5xx エラーなどの CloudFront エラーのデバッグが必要になることがあります。エラーは、Lambda 関数から返される無効なレスポンス、関数がトリガーされるときの実行時のエラー、または Lambda サービスによる実行スロットリングが原因のエラーの可能性があります。このトピックのセクションでは、どのタイプの障害が問題であるかを判別するための戦略、そしてその問題を解決するためのステップを共有します。

**注記**  
エラーをトラブルシューティングするときに CloudWatch ログファイルまたはメトリクスを確認する場合は、関数が実行される場所に最も近い AWS リージョン に表示または保存されていることに注意してください。したがって、例えば英国のユーザーがいるウェブサイトまたはウェブアプリケーションで、ディストリビューションに関連する Lambda 関数がある場合は、リージョンを変更してロンドン AWS リージョン の CloudWatch メトリクスまたはログファイルを表示する必要があります。詳細については、「[Lambda@Edge リージョンを判断する](#lambda-edge-testing-debugging-determine-region)」を参照してください。

**Topics**
+ [Lambda@Edge 関数をテストする](#lambda-edge-testing-debugging-test-function)
+ [CloudFront での Lambda@Edge 関数エラーを識別する](#lambda-edge-identifying-function-errors)
+ [無効な Lambda@Edge 関数レスポンス (検証エラー) のトラブルシューティング](#lambda-edge-testing-debugging-troubleshooting-invalid-responses)
+ [Lambda@Edge 関数実行エラーをトラブルシューティングする](#lambda-edge-testing-debugging-execution-errors)
+ [Lambda@Edge リージョンを判断する](#lambda-edge-testing-debugging-determine-region)
+ [アカウントがログを CloudWatch にプッシュするかどうかを判断する](#lambda-edge-testing-debugging-cloudwatch-logs-enabled)

## Lambda@Edge 関数をテストする
<a name="lambda-edge-testing-debugging-test-function"></a>

Lambda 関数をテストするには、スタンドアロンテストと統合テストの 2 つのステップがあります。

**スタンドアロン機能のテスト**  
CloudFront に Lambda 関数を追加する前に、Lambda コンソールでテスト機能を使用するか他の方法を使用して、必ず最初に機能をテストしてください。Lambda コンソールでのテストの詳細については、「AWS Lambda 開発者ガイド」の「[コンソールを使用して Lambda 関数を呼び出す](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html#get-started-invoke-manually)」を参照してください。**

**CloudFront での関数のオペレーションのテスト**  
統合テストを完了することが重要です。ここで、関数はディストリビューションに関連付けられ、CloudFront イベントに基づいて実行されます。関数が正しいイベントに対してトリガーされることを確認し、CloudFront に対して有効で正しいレスポンスを返します。例えば、イベント構造が正しいこと、有効なヘッダーだけが含まれていることなどを確認します。  
Lambda コンソールの関数で統合テストを繰り返す場合、コードを変更する際や関数を呼び出す CloudFront トリガーを変更する際は、Lambda@Edge チュートリアルのステップを参照しください。例えば、チュートリアルの「[ステップ 4: 関数を実行する CloudFront トリガーを追加する](lambda-edge-how-it-works-tutorial.md#lambda-edge-how-it-works-tutorial-add-trigger)」のステップで説明しているように、関数の番号付きバージョンを操作していることを確認します。  
変更を加えた場合やデプロイした場合、更新した関数と CloudFront トリガーがすべてのリージョンにレプリケートするまで数分かかることに注意してください。通常、これには数分かかりますが、最大で 15 分かかる場合があります。  
レプリケーションが終了したかどうかを確認するには、CloudFront コンソールに移動し、ディストリビューションを表示します。  

**レプリケーションのデプロイが完了したかどうかを確認するには**

1. CloudFront コンソール ([https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home)) を開きます。

1. ディストリビューション名を選択します。

1. ディストリビューションのステータスが [**進行中**] から [**デプロイ済み**] に戻ったことを確認します。この場合、関数はレプリケートされたことを意味します。続いて、次のセクションのステップに従って関数が機能することを確認します。
コンソールでのテストでは関数のロジックのみを検証します。また、Lambda@Edge に固有のサービスクォータ (以前は制限と呼ばれていました) は適用されないことに注意してください。

## CloudFront での Lambda@Edge 関数エラーを識別する
<a name="lambda-edge-identifying-function-errors"></a>

関数のロジックが正常に機能することを確認した後でも、CloudFront での関数の実行時に HTTP 5xx エラーが発生することがあります。HTTP 5xx エラーはさまざまな理由で返される可能性があります。これには、Lambda 関数エラーやその他の CloudFront の問題が含まれる場合があります。
+ Lambda@Edge 関数を使用している場合は、CloudFront コンソールのグラフを使用してエラーの原因を突き止め、それを修正することができます。例えば、HTTP 5xx エラーの原因が CloudFront によるものか、Lambda 関数によるものかを確認し、特定の関数については関連するログファイルを表示して問題を調査できます。
+ HTTP エラー全般を CloudFront でトラブルシューティングするには、[CloudFront でのエラーレスポンスステータスコードのトラブルシューティング](troubleshooting-response-errors.md) のトピックのトラブルシューティング手順を参照してください。

### CloudFront で Lambda@Edge 関数エラーが発生する原因
<a name="lambda-edge-testing-debugging-function-errors"></a>

Lambda 関数が HTTP 5xx エラーの原因となる可能性がある理由はいくつかあります。実行するトラブルシューティングステップはエラーのタイプによって異なります。エラーは次のように分類されます。

**Lambda 関数実行エラー**  
関数に未処理の例外があるか、コードにエラーがあって CloudFront が Lambda からレスポンスを得られない場合は、実行エラーが発生します。たとえば、コードにコールバック (エラー) が含まれている場合です。

**無効な Lambda 関数のレスポンスが CloudFront に返される**  
関数の実行後、CloudFront が Lambda からレスポンスを受け取ります。レスポンスのオブジェクト構造が [Lambda@Edge イベント構造](lambda-event-structure.md) に従わない場合、またはレスポンスに無効なヘッダーや他の無効なフィールドが含まれている場合、エラーが返されます。

**CloudFront での実行は、Lambda サービスのクォータ (以前は制限と呼ばれていました) のために調整されます。**  
Lambda サービスは各リージョンでの実行を制限し、クォータに達するとエラーが返されます。詳細については、「[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)」を参照してください。

### 障害のタイプを判断する方法
<a name="lambda-edge-testing-debugging-failure-type"></a>

デバッグするときにどこに焦点を合わせて CloudFront から返されたエラーを解決するかを決めるのに役立つように、なぜ CloudFront が HTTP エラーを返しているのかを識別することは役立ちます。これを開始するには、AWS マネジメントコンソール で CloudFront コンソールの [**Monitoring**] (モニタリング) セクションにあるグラフを使うことができます。CloudFront コンソールの [**Monitoring (モニタリング)**] セクションでのグラフ表示の詳細については、「[Amazon CloudWatch で CloudFront メトリクスをモニタリングする](monitoring-using-cloudwatch.md)」を参照してください。

次のグラフは、エラーが発生源によって返されたのか Lambda 関数によって返されたのかを追跡し、Lambda 関数からのエラーである場合に問題の種類を絞り込む場合に特に役立ちます。

**エラー率グラフ**  
各ディストリビューションの [**Overview**] タブに表示できるグラフの1つが、[**Error rates**] グラフです。このグラフは、ディストリビューションに対するすべてのリクエストに対するエラーの割合をパーセンテージで表示します。グラフは、Lambda 関数の合計エラー率、合計 4xx エラー、合計 5xx エラー、合計 5xx エラーを示しています。エラーの種類と量に基づいて、原因を調査してトラブルシューティングするための手順を実行できます。  

![\[CloudFront ディストリビューションのエラー率グラフ\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/images/Distribution-error-rate-pct-full.png)

+ Lambda エラーが表示された場合は、関数が返す特定の種類のエラーを調べることで、さらに詳しく調べることができます。[**Lambda@Edge errors**] タブには、特定の関数に関する問題を特定するのに役立つように、関数エラーをタイプ別に分類したグラフが含まれています。
+ CloudFront エラーが表示された場合は、トラブルシューティングを行い、オリジンエラーを修正したり、CloudFront 設定を変更したりすることができます。詳細については、「[CloudFront でのエラーレスポンスステータスコードのトラブルシューティング](troubleshooting-response-errors.md)」を参照してください。

**Execution エラーと無効な関数レスポンスグラフ**  
[**Lambda@Edge errors**] タブには、特定のディストリビューションに対する Lambda@Edge エラーをタイプ別に分類したグラフが含まれています。例えば、1 つのグラフに AWS リージョン 別の実行エラーがすべて表示されます。  
問題のトラブルシューティングを容易にするために、地域別に特定の関数のログファイルを開いて調べることで、特定の問題を探すことができます。  

**リージョン別に特定の関数のログファイルを表示するには**

1. **[Lambda@Edge エラー]** タブの **[関連する Lambda@Edge 関数]** で、関数名を選択し、**[メトリクスの表示]** を選択します。

1. 次に、関数名のページの右上隅で、**[関数ログの表示]** を選択し、リージョンを選択します。

   例えば、米国西部 (オレゴン) リージョンの **[エラー]** グラフに問題が表示される場合は、ドロップダウンリストからそのリージョンを選択します。これにより、Amazon CloudWatch コンソールが開きます。

1. そのリージョンの CloudWatch コンソールの **[ログストリーム]** で、ログストリームを選択して関数のイベントを表示します。
さらに、トラブルシューティングとエラーの修正に関する推奨事項については、この章の次のセクションを参照してください。

**スロットルグラフ**  
[**Lambda@Edge errors**] タブには、[**Throttles**] グラフも含まれます。場合によっては、リージョンの同時実行性のクォータに達すると、Lambda サービスがリージョンごとに関数呼び出しを調整します。制限の超過エラーが表示される場合は、Lambda サービスがリージョンの実行に課すクォータに関数が達しています。クォータの増加をリクエストする方法など、詳細については、「[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)」を参照してください。  

![\[Lambda@Edge 関数実行のスロットルグラフ。\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/images/Lambda-throttles-page.png)


HTTP エラーのトラブルシューティングでこの情報を使用する方法の例については、「[AWS でコンテンツ配信をデバッグするための 4 つのステップ](https://aws.amazon.com/blogs/networking-and-content-delivery/four-steps-for-debugging-your-content-delivery-on-aws/)」を参照してください。

## 無効な Lambda@Edge 関数レスポンス (検証エラー) のトラブルシューティング
<a name="lambda-edge-testing-debugging-troubleshooting-invalid-responses"></a>

問題が Lambda 検証エラーであると特定した場合は、Lambda 関数が CloudFront に無効なレスポンスを返していることを意味します。このセクションのガイダンスに従い、関数を確認し、レスポンスが CloudFront 要件に従っていることを確認する手順を実行します。

CloudFront は、次の 2 つの方法で Lambda 関数からのレスポンスを検証します。
+ **Lambda レスポンスは、必要なオブジェクト構造に従う必要があります。**不正なオブジェクト構造の例には次のようなものがあります。解析できない JSON、必須フィールドの欠落、レスポンスの無効なオブジェクト。詳細については、「[Lambda@Edge イベント構造](lambda-event-structure.md)」を参照してください。
+ **レスポンスには有効なオブジェクト値のみを含める必要があります。**レスポンスに有効なオブジェクトが含まれるがサポートされていない値がある場合、エラーが発生します。例には、許可されていない、または読み取り専用のヘッダーの追加または更新 (「[エッジ関数に対する制限](edge-functions-restrictions.md)」を参照)、ボディサイズの上限の超過 (Lambda@Edge [エラー](lambda-generating-http-responses.md#lambda-generating-http-responses-errors) トピックの「*生成されるレスポンスのサイズに対する制限」を参照*)、および無効な文字または値 (「[Lambda@Edge イベント構造](lambda-event-structure.md)」を参照) などがあります。

Lambda が CloudFront に無効なレスポンスを返すと、Lambda 関数が実行されるリージョンで CloudFront が CloudWatch にプッシュするログファイルに、エラーメッセージが書き込まれます。これは、無効なレスポンスがあるときにログファイルを CloudWatch に送信するデフォルトの動作です。ただし、機能をリリースする前に Lambda 関数を CloudFront と関連付けると、関数に対して有効にならない可能性があります。詳細については、このトピックの後半の「*アカウントがログを CloudWatch にプッシュするかどうかを判断する*」を参照してください。

CloudFront は、関数を実行した場所に対応するリージョンで、ディストリビューションに関連するロググループにログファイルをプッシュします。ロググループの形式は `/aws/cloudfront/LambdaEdge/DistributionId` です。ここで *DistributionId* はディストリビューションの ID です。CloudWatch ログファイルがあるリージョンを決定するには、このトピックの後半の「*Lambda@Edge のリージョンの判別*」を参照してください。

再現可能なエラーの場合、エラーになる新しいリクエストを作成し、障害のある CloudFront レスポンス (`X-Amz-Cf-Id` ヘッダー) でリクエスト ID を見つけて、ログファイル内の 1 つの障害を特定します。ログファイルのエントリには、エラーが返される理由を特定するのに役立つ情報が含まれます。また、対応する Lambda リクエスト ID もリスト表示されるため、1 つのリクエストのコンテキストでの根本原因を分析することもできます。

エラーが断続的な場合は、CloudFront アクセスログを使用して障害が発生したリクエストのリクエスト ID を見つけ、対応するエラーメッセージの CloudWatch Logs を検索します。詳細については、前のセクションの「*Determining the Type of Failure*」を参照してください。

## Lambda@Edge 関数実行エラーをトラブルシューティングする
<a name="lambda-edge-testing-debugging-execution-errors"></a>

Lambda 実行エラーが問題である場合は、Lambda 関数のログ記録ステートメントを作成しておくと、CloudWatch での関数の実行をモニタリングする CloudFront ログファイルにメッセージを書き込み、正常に機能しているかどうかを判断するのに役立ちます。その後、これらのステートメントを CloudWatch ログファイルで検索して、関数が正常に機能していることを確認できます。

**注記**  
Lambda@Edge 関数を変更していない場合でも、Lambda 関数の実行環境を更新すると、この関数に影響を与え、実行エラーが発生する可能性があります。テストおよび新しいバージョンへの移行の詳細については、「[Upcoming updates to the AWS Lambda and AWS Lambda@Edge execution environment](https://aws.amazon.com/blogs/compute/upcoming-updates-to-the-aws-lambda-execution-environment/)」を参照してください。

## Lambda@Edge リージョンを判断する
<a name="lambda-edge-testing-debugging-determine-region"></a>

Lambda@Edge 関数がトラフィックを受信しているリージョンを確認するには、 のCloudFront コンソールでその関数のメトリクスを表示しますAWS マネジメントコンソール メトリックスは AWS リージョンごとに表示されます。同じページで、リージョンを選択してそのリージョンのログファイルを表示し、問題を調査することができます。CloudFront が Lambda 関数を実行したときに作成されたログファイルを表示するには、正しい AWS リージョンの CloudWatch ログファイルを確認する必要があります。

CloudFront コンソールの [**Monitoring (モニタリング)**] セクションでのグラフ表示の詳細については、「[Amazon CloudWatch で CloudFront メトリクスをモニタリングする](monitoring-using-cloudwatch.md)」を参照してください。

## アカウントがログを CloudWatch にプッシュするかどうかを判断する
<a name="lambda-edge-testing-debugging-cloudwatch-logs-enabled"></a>

デフォルトでは、CloudFront によって無効な Lambda 関数レスポンスのログ記録が有効になり、[Lambda@Edge 用のサービスにリンクされたロール](lambda-edge-permissions.md#using-service-linked-roles-lambda-edge) のいずれかを使用してログファイルが CloudWatch にプッシュされます。無効な Lambda 関数レスポンスのログ機能がリリースされた前に CloudFront に追加した Lambda@Edge 関数がある場合は、CloudFront トリガーを追加するなど、Lambda@Edge 設定を次に更新するときにログ記録が有効になります。

次を実行して、アカウントでログファイルを CloudWatch にプッシュすることが有効になっているか確認できます。
+ **CloudWatch にログが表示されるかどうかを確認する** – Lambda@Edge 関数が実行されたリージョンを確認します。詳細については、「[Lambda@Edge リージョンを判断する](#lambda-edge-testing-debugging-determine-region)」を参照してください。
+ **関連するサービスリンクロールが IAM のアカウントに存在するかどうかを確認する –** アカウントに IAM ロール `AWSServiceRoleForCloudFrontLogger` が必要です。このロールの詳細については、「[Lambda@Edge 用のサービスにリンクされたロール](lambda-edge-permissions.md#using-service-linked-roles-lambda-edge)」を参照してください。

# Lambda@Edge 関数とレプリカを削除する
<a name="lambda-edge-delete-replicas"></a>

Lambda@Edge 関数を削除できるのは、関数のレプリカが CloudFront によって削除された場合のみです。Lambda 関数のレプリカは、次のような状況では自動的に削除されます。
+ すべての CloudFront ディストリビューションから関数の最後の関連付けを削除した後。複数のディストリビューションで関数が使用されている場合、最後のディストリビューションから関数の関連付けを削除した後にのみ、レプリカが削除されます。
+ 関数が関連付けられた最後のディストリビューションを削除した後。

レプリカは通常、数時間以内に削除されます。Lambda@Edge 関数のレプリカを手動で削除することはできません。これにより、まだ使用中のレプリカが削除され、エラーが発生する状況を防ぐことができます。

**警告**  
CloudFront の外部で Lambda@Edge 関数のレプリカを使用するアプリケーションを構築しないでください。これらのレプリカは、ディストリビューションとの関連付けが削除されるか、ディストリビューション自体が削除されると削除されます。外部のアプリケーションが依存するレプリカが警告なしに削除されて、エラーが発生することがあります。

**CloudFront ディストリビューションから Lambda@Edge 関数の関連付けを削除するには**

1. AWS マネジメントコンソールにサインインし、[https://console.aws.amazon.com/cloudfront/v4/home](https://console.aws.amazon.com/cloudfront/v4/home) で CloudFront コンソールを開きます。

1. 削除する Lambda@Edge 関数の関連付けがあるディストリビューションの ID を選択します。

1. [**Behaviors**] タブを選択します。

1. 削除する Lambda@Edge 関数の関連付けがあるキャッシュ動作を選択し、**[編集]** を選択します。

1. Lambda@Edge 関数の関連付けを削除するには、**[関数の関連付け]**、**[関数タイプ]**、**[関連付けなし]** の順に選択します。

1. **[Save changes]** (変更の保存) をクリックします。

CloudFront ディストリビューションから Lambda@Edge 関数の関連付けを削除した後、必要に応じて から Lambda 関数または関数バージョンを削除することもできますAWS Lambda 関数の関連付けを削除したら、Lambda@Edge 関数のレプリカをクリーンアップできるようになるまで数時間待ちます。その後、Lambda コンソール、AWS CLI、Lambda API、または AWS SDK を使用して関数を削除できます。

特定のバージョンの Lambda 関数が、どの CloudFront ディストリビューションにも関連付けられていない場合は、このバージョンを削除することもできます。**Lambda 関数バージョンのすべての関連付けを削除したら、数時間待ちます。その後、関数バージョンを削除できます。

# Lambda@Edge イベント構造
<a name="lambda-event-structure"></a>

以下のトピックでは、CloudFront がトリガーされたときに Lambda@Edge 関数に渡すリクエストおよびレスポンスイベントオブジェクトについて説明します。

**Topics**
+ [動的オリジン選択](#lambda-event-content-based-routing)
+ [リクエストイベント](#lambda-event-structure-request)
+ [レスポンスイベント](#lambda-event-structure-response)

## 動的オリジン選択
<a name="lambda-event-content-based-routing"></a>

[キャッシュ動作でパスパターン](DownloadDistValuesCacheBehavior.md#DownloadDistValuesPathPattern)を使用すると、リクエストされたオブジェクトのパスと名前 (`images/*.jpg` など) に基づいて、リクエストをオリジンにルーティングできます。Lambda@Edge を使用すると、リクエストヘッダーの値など他のプロパティに基づいても、リクエストをオリジンにルーティングできます。

この動的オリジン選択が便利な状況がいくつかあります。たとえば、グローバルな負荷分散に役立つように、地理的に異なるリージョンのオリジンにリクエストを分散させる場合です。あるいは、機能 (ボット処理、SEO 最適化、認証など) が異なるさまざまなオリジンに、リクエストを選択的にルーティングする場合です。この機能の使用方法を示すコードサンプルについては、「[コンテンツベースの動的オリジンの選択 - 例](lambda-examples.md#lambda-examples-content-based-routing-examples)」を参照してください。

CloudFront のオリジンリクエストイベントで、イベント構造の `origin` オブジェクトには、パスパターンに基づいてリクエストがルーティングされるオリジンに関する情報が含まれます。リクエストを別のオリジンにルーティングするように、`origin` オブジェクトの値を更新できます。`origin` オブジェクトを更新するときに、ディストリビューションのオリジンを定義する必要はありません。Amazon S3 オリジンオブジェクトをカスタムオリジンオブジェクトに置き換えたり、その逆にすることもできます。ただし、カスタムオリジンと Amazon S3 オリジンのどちらか (両方は不可) を通じて、リクエストごとに 1 つのオリジンしか指定できません。

## リクエストイベント
<a name="lambda-event-structure-request"></a>

以下のトピックでは、[ビューワーおよびオリジンリクエストイベント](lambda-cloudfront-trigger-events.md)の Lambda 関数に CloudFront が渡すオブジェクトの構造を示します。これらの例は、本文のない `GET` リクエストを示しています。例に続いて、ビューワーとオリジンリクエストイベントで使用可能なすべてのフィールドのリストを示します。

**Topics**
+ [ビューワーリクエストの例](#example-viewer-request)
+ [オリジンリクエストの例](#example-origin-request)
+ [リクエストイベントフィールド](#request-event-fields)

### ビューワーリクエストの例
<a name="example-viewer-request"></a>

次の例は、ビューワーリクエストイベントオブジェクトを示しています。

```
{
  "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": "/"
        }
      }
    }
  ]
}
```

### オリジンリクエストの例
<a name="example-origin-request"></a>

次の例は、オリジンリクエストイベントオブジェクトを示しています。

```
{
  "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,
              "responseCompletionTimeout": 30,
              "sslProtocols": [
                "TLSv1",
                "TLSv1.1",
                "TLSv1.2"
              ]
            }
          },
          "querystring": "",
          "uri": "/"
        }
      }
    }
  ]
}
```

### リクエストイベントフィールド
<a name="request-event-fields"></a>

リクエストイベントオブジェクトデータは、`config` (`Records.cf.config`) と `request` (`Records.cf.request`) の 2 つのサブオブジェクトに含まれています。次のリストは、各サブオブジェクトのフィールドを示しています。

#### 設定オブジェクトのフィールド
<a name="request-event-fields-config"></a>

次のリストでは、`config` オブジェクト (`Records.cf.config`) のフィールドについて説明します。

**`distributionDomainName` (読み取り専用)**  
リクエストに関連付けられているディストリビューションのドメイン名。

**`distributionID` (読み取り専用)**  
リクエストに関連付けられているディストリビューションの ID。

**`eventType` (読み取り専用)**  
リクエストに関連付けられているトリガーのタイプ (`viewer-request` または `origin-request`)。

**`requestId` (読み取り専用)**  
ビューワーから CloudFront へのリクエストを一意に識別する暗号化された文字列。`requestId` の値は CloudFront アクセスログにも `x-edge-request-id` として表示されます。詳細については、「[アクセスログ (標準ログ)](AccessLogs.md)」および「[ログファイルのフィールド](standard-logs-reference.md#BasicDistributionFileFormat)」を参照してください。

#### リクエストオブジェクトのフィールド
<a name="request-event-fields-request"></a>

次のリストでは、`request` オブジェクト (`Records.cf.request`) のフィールドについて説明します。

**`clientIp` (読み取り専用)**  
リクエストを行ったビューワーの IP アドレス。ビューワーが HTTP プロキシまたはロードバランサーを使用してリクエストを送った場合、この値はプロキシまたはロードバランサーの IP アドレスです。

**headers (読み書き)**  
リクエストのヘッダー。次の点に注意してください。  
+ `headers` オブジェクトのキーは標準の HTTP ヘッダー名を小文字にしたものです。小文字のキーを使用して、大文字と小文字を区別せずにヘッダー値にアクセスできます。
+ 各ヘッダーオブジェクト (`headers["accept"]`、`headers["host"]` など) はキーと値のペアの配列です。返されたヘッダーの配列には、リクエストの値ごとに 1 つのキーと値のペアが含まれます。
+ `key` には、HTTP リクエストに表示されるヘッダーの大文字と小文字を区別する名前が含まれます (`Host`、`User-Agent`、`X-Forwarded-For`、`Cookie` など)。
+ `value` には、HTTP リクエストに表示されるヘッダー値が含まれます。
+ Lambda 関数がリクエストヘッダーを追加または変更し、ヘッダー `key` フィールドを含めない場合、Lambda@Edge は指定したヘッダー名を使用してヘッダー `key` を自動的に挿入します。ヘッダー名をどのようにフォーマットしたかにかかわらず、自動的に挿入されるヘッダーキーの各パートは、先頭が大文字になり、ハイフン (-) で区切られます。

  たとえば、ヘッダー `key` なしで次のようなヘッダーを追加できます。

  ```
  "user-agent": [
    {
      "value": "ExampleCustomUserAgent/1.X.0"
    }
  ]
  ```

  この例では、Lambda@Edge は `"key": "User-Agent"` を自動的に挿入します。
ヘッダー使用の制限の詳細については、「[エッジ関数に対する制限](edge-functions-restrictions.md)」を参照してください。

**`method` (読み取り専用)**  
リクエストの HTTP メソッド。

**`querystring` (読み書き)**  
リクエスト内のクエリ文字列 (存在する場合)。リクエストにクエリ文字列が含まれていない場合でも、イベントオブジェクトには `querystring` が含まれ、値が空になります。クエリ文字列の詳細については、「[クエリ文字列パラメータに基づいてコンテンツをキャッシュする](QueryStringParameters.md)」を参照してください。

**`uri` (読み書き)**  
リクエストされたオブジェクトの相対パス。Lambda 関数が `uri` 値を変更する場合、次の点に注意してください。  
+ 新しい `uri` 値は、スラッシュ (/) で始める必要があります。
+ 関数で `uri` 値を変更すると、ビューワーがリクエストしているオブジェクトが変更されます。
+ 関数で `uri` 値を変更しても、リクエストのキャッシュ動作や送信先オリジンは*変わりません*。

**`body` (読み書き)**  
HTTP リクエストの本文。`body` 構造には、次のフィールドを含めることができます。    
**`inputTruncated` (読み取り専用)**  
本文が Lambda@Edge で切り捨てられたかどうかを示すブーリアン型フラグ。詳細については、「[[本文を含める] オプションを使用する場合のリクエスト本文に対する制限](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body)」を参照してください。  
**`action` (読み書き)**  
本文で実行する予定のアクション。`action` のオプションは次のとおりです。  
+ `read-only:` これがデフォルト値です。Lambda 関数からレスポンスを返す際に、`action` が読み取り専用の場合、Lambda@Edge は `encoding` または `data` への変更をすべて無視します。
+ `replace:` オリジンに送信される本文を置き換えるときに指定します。  
**`encoding` (読み書き)**  
本文のエンコード。Lambda@Edge が Lambda 関数に本文を公開すると、まず本文を base64-encoding に変換します。本文を置き換える `replace` として `action` を選択した場合、`base64` (デフォルト) または `text` エンコードを使用することもできます。`encoding` を `base64` と指定したが本文が有効な base64 でない場合、CloudFront はエラーを返します。  
**`data` (読み書き)**  
リクエストボディのコンテンツ。

**`origin` (読み書き) (オリジンイベントのみ)**  
リクエストの送信先のオリジン。`origin` 構造には、*オリジンを 1 つだけ*含める必要があります。カスタムオリジンでも Amazon S3 オリジンでも構いません。  
指定するオリジンタイプ (カスタムオリジンまたは Amazon S3 オリジン) に応じて、以下のフィールドをリクエストに指定する必要があります。    
**`customHeaders` (読み取り/書き込み) (カスタムおよび Amazon S3 オリジン)**  
(オプション) 各カスタムヘッダーの名前と値のペアを指定することで、カスタムヘッダーをリクエストに含めることができます。許可されていないヘッダーを追加することはできず、同じ名前のヘッダーを `Records.cf.request.headers` に含めることもできません。[リクエストヘッダーに関する注意事項](#request-event-fields-request-headers)は、カスタムヘッダーにも適用されます。詳細については、「[CloudFront でオリジンリクエストに追加できないカスタムヘッダー](add-origin-custom-headers.md#add-origin-custom-headers-denylist)」および「[エッジ関数に対する制限](edge-functions-restrictions.md)」を参照してください。  
**`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～120 の範囲の数値を指定する必要があります。  
**`port` (読み書き) (カスタムオリジンのみ)**  
カスタムオリジンでの CloudFront の接続先ポート。ポートは 80 または 443 であるか、1024 〜 65535 の範囲の数値であることが必要です。  
**`protocol` (読み書き) (カスタムオリジンのみ)**  
オリジンに接続するとき CloudFront が使用する接続プロトコル。ここには、`http` または `https` が表示されます。  
**`readTimeout` (読み取り/書き込み) (カスタムおよび Amazon S3 オリジン)**  
オリジンにリクエストを送信した後、CloudFront がレスポンスを待機する時間 (秒単位)。これは、レスポンスのパケットを受信してから次のパケットを受信するまで CloudFront が待機する時間も指定します。この値には、1～120 の範囲の数値を指定する必要があります。  
高いクォータが必要な場合は、「[オリジン別の応答タイムアウト](cloudfront-limits.md#limits-web-distributions)」を参照してください。  
**`responseCompletionTimeout` (読み取り/書き込み) (カスタムおよび Amazon S3 オリジン)**  
CloudFront からオリジンへのリクエストを開いたままにして応答を待機できる時間 (秒単位)。この時間までにオリジンから完全な応答が受信されない場合、CloudFront は接続を終了します。  
`responseCompletionTimeout` の値は、`readTimeout` の値以上にする必要があります。この値を 0 に設定すると、設定した以前の値はすべて削除され、デフォルトに戻ります。また、イベントリクエストから `responseCompletionTimeout` フィールドを削除することでもこれを実現できます。  
**`sslProtocols` (読み書き) (カスタムオリジンのみ)**  
オリジンとの HTTPS 接続を確立するときに CloudFront が使用できる最小限の SSL/TLS プロトコル。値は、`TLSv1.2`、`TLSv1.1`、`TLSv1`、または `SSLv3` のいずれかです。  
**`authMethod` (読み取り/書き込み) (Amazon S3 オリジンのみ)**  
[オリジンアクセスアイデンティティ (OAI)](private-content-restricting-access-to-s3.md#private-content-restricting-access-to-s3-oai) を使用している場合は、このフィールドを `origin-access-identity` に設定します。OAI を使用していない場合は、`none` に設定します。`authMethod` を `origin-access-identity` に設定した場合、いくつかの要件があります。  
+ `region` を指定する必要があります (次のフィールドを参照)。
+ リクエストをある Amazon S3 オリジンから別のオリジンに変更する場合は、同じ OAI を使用する必要があります。
+ リクエストをカスタムオリジンから Amazon S3 オリジンに変更する場合、OAI を使用することはできません。
このフィールドは[オリジンアクセスコントロール (OAC) ](private-content-restricting-access-to-s3.md)をサポートしていません。  
**`region` (読み取り/書き込み) (Amazon S3 オリジンのみ)**  
Amazon S3 バケットの AWS リージョン。これは、`authMethod` を `origin-access-identity` に設定した場合にのみ必要です。

## レスポンスイベント
<a name="lambda-event-structure-response"></a>

以下のトピックでは、[ビューワーおよびオリジンレスポンスイベント](lambda-cloudfront-trigger-events.md)の Lambda 関数に CloudFront が渡すオブジェクトの構造を示します。例に続いて、ビューワーとオリジンレスポンスイベントで使用可能なすべてのフィールドのリストを示します。

**Topics**
+ [オリジンレスポンスの例](#lambda-event-structure-response-origin)
+ [ビューワーレスポンスの例](#lambda-event-structure-response-viewer)
+ [レスポンスイベントのフィールド](#response-event-fields)

### オリジンレスポンスの例
<a name="lambda-event-structure-response-origin"></a>

次の例は、オリジンレスポンスイベントオブジェクトを示しています。

```
{
  "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,
              "responseCompletionTimeout": 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"
        }
      }
    }
  ]
}
```

### ビューワーレスポンスの例
<a name="lambda-event-structure-response-viewer"></a>

次の例は、ビューワーレスポンスイベントオブジェクトを示しています。

```
{
  "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"
        }
      }
    }
  ]
}
```

### レスポンスイベントのフィールド
<a name="response-event-fields"></a>

レスポンスイベントオブジェクトデータは、`config` (`Records.cf.config`)、`request` (`Records.cf.request`)、`response` (`Records.cf.response`) の 3 つのサブオブジェクトに含まれています。リクエストオブジェクトのフィールドの詳細については、「[リクエストオブジェクトのフィールド](#request-event-fields-request)」を参照してください。次のリストでは、`config` および `response` サブオブジェクトのフィールドについて説明します。

#### 設定オブジェクトのフィールド
<a name="response-event-fields-config"></a>

次のリストでは、`config` オブジェクト (`Records.cf.config`) のフィールドについて説明します。

**`distributionDomainName` (読み取り専用)**  
レスポンスに関連付けられているディストリビューションのドメイン名。

**`distributionID` (読み取り専用)**  
レスポンスに関連付けられているディストリビューションの ID。

**`eventType` (読み取り専用)**  
レスポンスに関連付けられているトリガーのタイプ (`origin-response` または `viewer-response`)。

**`requestId` (読み取り専用)**  
このレスポンスが関連付けられているビューワーから CloudFront へのリクエストを一意に識別する暗号化された文字列。`requestId` の値は CloudFront アクセスログにも `x-edge-request-id` として表示されます。詳細については、「[アクセスログ (標準ログ)](AccessLogs.md)」および「[ログファイルのフィールド](standard-logs-reference.md#BasicDistributionFileFormat)」を参照してください。

#### レスポンスオブジェクトのフィールド
<a name="response-event-fields-response"></a>

次のリストでは、`response` オブジェクト (`Records.cf.response`) のフィールドについて説明します。Lambda@Edge 関数を使用して HTTP レスポンスを生成する方法については、「[リクエストトリガーでの HTTP レスポンスを生成する](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests)」を参照してください。

**`headers` (読み書き)**  
レスポンスのヘッダー。次の点に注意してください。  
+ `headers` オブジェクトのキーは標準の HTTP ヘッダー名を小文字にしたものです。小文字のキーを使用して、大文字と小文字を区別せずにヘッダー値にアクセスできます。
+ 各ヘッダーオブジェクト (`headers["content-type"]`、`headers["content-length"]` など) はキーと値のペアの配列です。返されたヘッダーの配列には、レスポンスの値ごとに 1 つのキーと値のペアが含まれます。
+ `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"` を自動的に挿入します。
ヘッダー使用の制限の詳細については、「[エッジ関数に対する制限](edge-functions-restrictions.md)」を参照してください。

**`status`**  
レスポンスの HTTP ステータスコード。

**`statusDescription`**  
レスポンスの HTTP ステータスの説明。

# リクエストとレスポンスを使用する
<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)
+ [include body オプションを選択してリクエストボディにアクセスする](#lambda-include-body-access)

## オリジンフェイルオーバーで Lambda@Edge 関数を使用する
<a name="lambda-and-origin-failover"></a>

例えば、高い可用性を確保するために設定したオリジンフェイルオーバーなど、オリジングループで設定した CloudFront ディストリビューションで Lambda@Edge 関数を使用できます。オリジングループで 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 関数が HTTP レスポンスを生成することで、CloudFront がレスポンスをオリジンに転送せずに直接ビューワーに返すようにできます。HTTP レスポンスを生成することで、オリジンの負荷が軽減され、通常はビューワーのレイテンシーも短縮されます。

以下に示しているのは、HTTP レスポンスを生成する一般的なシナリオです。
+ 小さいウェブページをビューワーに返す。
+ HTTP 301 または 302 ステータスコードを返して、ユーザーを別のウェブページにリダイレクトする。
+ ユーザーが認証されない場合に HTTP 401 ステータスコードをビューワーに返す。

Lambda@Edge 関数は、以下の CloudFront イベントが発生したときに 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"]` など) はキーと値のペアの配列です。返されたヘッダーの配列には、生成されたレスポンスの値ごとに 1 つのキーと値のペアが含まれます。
+ `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 (No Content) が指定されている**  
関数がビューワーリクエストによってトリガーされると、CloudFront は、以下の両方が当てはまる場合に、HTTP 502 ステータスコード (Bad Gateway) をビューワーに返します。  
+ `status` の値が 204 (No Content) である。
+ このレスポンスに `body` の値が含まれている。
これは、`HTTP 204` レスポンスにはメッセージ本文を含める必要がないことを述べている RFC 2616 のオプションの制限を Lambda@Edge が適用しているためです。

**生成されるレスポンスのサイズ制限を超えている**  
Lambda 関数によって生成されるレスポンスの最大サイズは、関数をトリガーするイベントによって異なります。  
+ **ビューワーリクエストイベント** - 40 KB
+ **オリジンリクエストイベント** - 1 MB
レスポンスがこの許容サイズを超えると、CloudFront が HTTP 502 ステータスコード (Bad Gateway) をビューワーに返します。

#### 必須フィールド
<a name="lambda-generating-http-responses-required-fields"></a>

`status` フィールドは必須です。

その他のすべてのフィールドはオプションです。

## オリジンレスポンストリガーでの HTTP レスポンスを更新する
<a name="lambda-updating-http-responses"></a>

CloudFront がオリジンサーバーから HTTP レスポンスを受け取ったときに、キャッシュ動作に関連付けられた origin-response トリガーがあれば、HTTP レスポンスを変更して、オリジンから返されたものを上書きできます。

以下に示しているのは、HTTP レスポンスを更新する一般的なシナリオです。
+ オリジンがエラーステータスコード (4xx または 5xx) を返すと、ステータスを変更して HTTP 200 ステータスコードを設定し、ビューワーに返す静的な本文コンテンツを作成する。サンプルコードについては、「[例: オリジンレスポンストリガーを使用してエラーステータスコードを 200 に更新する](lambda-examples.md#lambda-examples-custom-error-static-body)」を参照してください。
+ オリジンがエラーステータスコード (4xx または 5xx) を返すと、ステータスを変更して HTTP 301 または HTTP 302 ステータスコードを設定し、ユーザーを別のウェブサイトにリダイレクトする。サンプルコードについては、「[例: オリジンレスポンストリガーを使用してエラーステータスコードを 302 に更新する](lambda-examples.md#lambda-examples-custom-error-new-site)」を参照してください。

**注記**  
関数は `200` と `599` の間 (両端を含む) のステータス値を返す必要があります。そうでない場合、CloudFront はエラーをビューワーに返します。

ビューワーとオリジンのリクエストイベントの HTTP レスポンスを置き換えることもできます。詳細については、「[リクエストトリガーでの HTTP レスポンスを生成する](#lambda-generating-http-responses-in-requests)」を参照してください。

HTTP レスポンスを使用する場合、Lambda@Edge は、オリジンサーバーから返された本文を origin-response トリガーに公開しません。必要な値に設定することで静的なコンテンツ本文を生成したり、値を空に設定することで関数内の本文を削除したりできます。関数内の本文フィールドを更新しない場合は、オリジンサーバーによって返された元の本文がビューワーに返されます。

## include body オプションを選択してリクエストボディにアクセスする
<a name="lambda-include-body-access"></a>

書き込み可能な HTTP メソッド (POST、PUT、DELETE など) のリクエストのボディを Lambda@Edge で公開することを選択できるため、Lambda 関数でそのボディにアクセスできます。読み取り専用アクセスを選択することも、ボディを置き換えることを指定することもできます。

このオプションを有効にするには、ビューワーリクエストやオリジンリクエストイベントのために関数に CloudFront トリガーを作成するとき、[**ボディを含める**] を選択します。詳細については、「[Lambda@Edge 関数のトリガーを追加する](lambda-edge-add-triggers.md)」を参照してください。または、関数で [**ボディを含める**] を使用する方法については、「[Lambda@Edge イベント構造](lambda-event-structure.md)」を参照してください。

この機能を使用する場合のシナリオには次のようなものがあります。
+ お客様の入力データをオリジンサーバーに返送することなく、「お問い合わせ」フォームのようなウェブフォームを処理します。
+ ビューワーブラウザによって送信されるウェブビーコンデータを収集し、エッジで処理します。

サンプルコードについては、「[Lambda@Edge 関数の例](lambda-examples.md)」を参照してください。

**注記**  
リクエストボディが大きい場合は、Lambda@Edge によって切り捨てられます。最大サイズ制限と切り捨ての詳細については、「[[本文を含める] オプションを使用する場合のリクエスト本文に対する制限](lambda-at-edge-function-restrictions.md#lambda-at-edge-restrictions-request-body)」を参照してください。

# Lambda@Edge 関数の例
<a name="lambda-examples"></a>

Amazon CloudFront で Lambda 関数を使用するには、以下の例を参照してください。

**注記**  
Lambda@Edge 関数にランタイム Node.js 18 以降を選択すると、`index.mjs` ファイルが自動的に作成されます。次のコード例を使用するには、`index.mjs` ファイルの名前を `index.js` に変更します。

**Topics**
+ [一般的な例](#lambda-examples-general-examples)
+ [レスポンスを生成する - 例](#lambda-examples-generated-response-examples)
+ [クエリ文字列 - 例](#lambda-examples-query-string-examples)
+ [国またはデバイスタイプヘッダー別のコンテンツのパーソナライズ - 例](#lambda-examples-redirecting-examples)
+ [コンテンツベースの動的オリジンの選択 - 例](#lambda-examples-content-based-routing-examples)
+ [エラーステータスを更新する - 例](#lambda-examples-update-error-status-examples)
+ [リクエストボディにアクセスする - 例](#lambda-examples-access-request-body-examples)

## 一般的な例
<a name="lambda-examples-general-examples"></a>

以下の例は、CloudFront で Lambda@Edge を使用する一般的な方法を示しています。

**Topics**
+ [例: A/B テスト](#lambda-examples-a-b-testing)
+ [例: レスポンスヘッダーをオーバーライドする](#lambda-examples-overriding-response-header)

### 例: A/B テスト
<a name="lambda-examples-a-b-testing"></a>

次の例を使用すると、リダイレクトを作成したり URL を変更したりすることなく、2 つの異なるバージョンのイメージをテストできます。この例では、ビューワーリクエスト内の Cookie を読み取り、それに応じてリクエスト URL を変更します。ビューワーがいずれかの期待値を使用して Cookie を送信しない場合、例ではビューワーを URL のいずれかにランダムに割り当てます。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    if (request.uri !== '/experiment-pixel.jpg') {
        // do not process if this is not an A-B test request
        callback(null, request);
        return;
    }

    const cookieExperimentA = 'X-Experiment-Name=A';
    const cookieExperimentB = 'X-Experiment-Name=B';
    const pathExperimentA = '/experiment-group/control-pixel.jpg';
    const pathExperimentB = '/experiment-group/treatment-pixel.jpg';

    /*
     * Lambda at the Edge headers are array objects.
     *
     * Client may send multiple Cookie headers, i.e.:
     * > GET /viewerRes/test HTTP/1.1
     * > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3
     * > Cookie: First=1; Second=2
     * > Cookie: ClientCode=abc
     * > Host: example.com
     *
     * You can access the first Cookie header at headers["cookie"][0].value
     * and the second at headers["cookie"][1].value.
     *
     * Header values are not parsed. In the example above,
     * headers["cookie"][0].value is equal to "First=1; Second=2"
     */
    let experimentUri;
    if (headers.cookie) {
        for (let i = 0; i < headers.cookie.length; i++) {
            if (headers.cookie[i].value.indexOf(cookieExperimentA) >= 0) {
                console.log('Experiment A cookie found');
                experimentUri = pathExperimentA;
                break;
            } else if (headers.cookie[i].value.indexOf(cookieExperimentB) >= 0) {
                console.log('Experiment B cookie found');
                experimentUri = pathExperimentB;
                break;
            }
        }
    }

    if (!experimentUri) {
        console.log('Experiment cookie has not been found. Throwing dice...');
        if (Math.random() < 0.75) {
            experimentUri = pathExperimentA;
        } else {
            experimentUri = pathExperimentB;
        }
    }

    request.uri = experimentUri;
    console.log(`Request uri set to "${request.uri}"`);
    callback(null, request);
};
```

------
#### [ Python ]

```
import json
import random

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    if request['uri'] != '/experiment-pixel.jpg':
        # Not an A/B Test
        return request

    cookieExperimentA, cookieExperimentB = 'X-Experiment-Name=A', 'X-Experiment-Name=B'
    pathExperimentA, pathExperimentB = '/experiment-group/control-pixel.jpg', '/experiment-group/treatment-pixel.jpg'

    '''
    Lambda at the Edge headers are array objects.

    Client may send multiple cookie headers. For example:
    > GET /viewerRes/test HTTP/1.1
    > User-Agent: curl/7.18.1 (x86_64-unknown-linux-gnu) libcurl/7.18.1 OpenSSL/1.0.1u zlib/1.2.3
    > Cookie: First=1; Second=2
    > Cookie: ClientCode=abc
    > Host: example.com

    You can access the first Cookie header at headers["cookie"][0].value
    and the second at headers["cookie"][1].value.

    Header values are not parsed. In the example above,
    headers["cookie"][0].value is equal to "First=1; Second=2"
    '''

    experimentUri = ""

    for cookie in headers.get('cookie', []):
        if cookieExperimentA in cookie['value']:
            print("Experiment A cookie found")
            experimentUri = pathExperimentA
            break
        elif cookieExperimentB in cookie['value']:
            print("Experiment B cookie found")
            experimentUri = pathExperimentB
            break

    if not experimentUri:
        print("Experiment cookie has not been found. Throwing dice...")
        if random.random() < 0.75:
            experimentUri = pathExperimentA
        else:
            experimentUri = pathExperimentB

    request['uri'] = experimentUri
    print(f"Request uri set to {experimentUri}")
    return request
```

------

### 例: レスポンスヘッダーをオーバーライドする
<a name="lambda-examples-overriding-response-header"></a>

以下の例は、レスポンスヘッダーの値を別のヘッダーの値に基づいて変更する方法を示しています。

------
#### [ Node.js ]

```
export const handler = async (event) => {
    const response = event.Records[0].cf.response;
    const headers = response.headers;

    const headerNameSrc = 'X-Amz-Meta-Last-Modified';
    const headerNameDst = 'Last-Modified';

    if (headers[headerNameSrc.toLowerCase()]) {
        headers[headerNameDst.toLowerCase()] = [{
            key: headerNameDst,
            value: headers[headerNameSrc.toLowerCase()][0].value,
        }];
        console.log(`Response header "${headerNameDst}" was set to ` +
                    `"${headers[headerNameDst.toLowerCase()][0].value}"`);
    }

    return response;
};
```

------
#### [ Python ]

```
import json 

def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    headers = response['headers']
    
    header_name_src = 'X-Amz-Meta-Last-Modified'
    header_name_dst = 'Last-Modified'
    
    if headers.get(header_name_src.lower()):
        headers[header_name_dst.lower()] = [{
            'key': header_name_dst,
            'value': headers[header_name_src.lower()][0]['value']
        }]
        print(f'Response header "{header_name_dst}" was set to '
              f'"{headers[header_name_dst.lower()][0]["value"]}"')
    
    return response
```

------

## レスポンスを生成する - 例
<a name="lambda-examples-generated-response-examples"></a>

以下の例は、Lambda@Edge を使用してレスポンスを生成する方法を示しています。

**Topics**
+ [例: 静的コンテンツを提供する (生成されたレスポンス)](#lambda-examples-static-web-server)
+ [例: HTTP リダイレクトを生成する (生成されたレスポンス)](#lambda-examples-http-redirect)

### 例: 静的コンテンツを提供する (生成されたレスポンス)
<a name="lambda-examples-static-web-server"></a>

次の例は、Lambda 関数を使用して静的ウェブサイトコンテンツを提供する方法を示しています。これにより、オリジンサーバーの負荷と全体的なレイテンシーが軽減されます。

**注記**  
HTTP レスポンスは、ビューワーリクエストおよびオリジンリクエストのイベントに対して生成できます。詳細については、「[リクエストトリガーでの HTTP レスポンスを生成する](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests)」を参照してください。  
オリジンレスポンスイベントで HTTP レスポンスのボディを置き換えたり、削除することもできます。詳細については、「[オリジンレスポンストリガーでの HTTP レスポンスを更新する](lambda-generating-http-responses.md#lambda-updating-http-responses)」を参照してください。

------
#### [ Node.js ]

```
'use strict';

const content = `
<\!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Simple Lambda@Edge Static Content Response</title>
  </head>
  <body>
    <p>Hello from Lambda@Edge!</p>
  </body>
</html>
`;

exports.handler = (event, context, callback) => {
    /*
     * Generate HTTP OK response using 200 status code with HTML body.
     */
    const response = {
        status: '200',
        statusDescription: 'OK',
        headers: {
            'cache-control': [{
                key: 'Cache-Control',
                value: 'max-age=100'
            }],
            'content-type': [{
                key: 'Content-Type',
                value: 'text/html'
            }]
        },
        body: content,
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
import json

CONTENT = """
<\!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Simple Lambda@Edge Static Content Response</title>
</head>
<body>
    <p>Hello from Lambda@Edge!</p>
</body>
</html>
"""

def lambda_handler(event, context):
    # Generate HTTP OK response using 200 status code with HTML body.
    response = {
        'status': '200',
        'statusDescription': 'OK',
        'headers': {
            'cache-control': [
                {
                    'key': 'Cache-Control',
                    'value': 'max-age=100'
                }
            ],
            "content-type": [
                {
                    'key': 'Content-Type',
                    'value': 'text/html'
                }
            ]
        },
        'body': CONTENT
    }
    return response
```

------

### 例: HTTP リダイレクトを生成する (生成されたレスポンス)
<a name="lambda-examples-http-redirect"></a>

次の例は、HTTP リダイレクトを生成する方法を示しています。

**注記**  
HTTP レスポンスは、ビューワーリクエストおよびオリジンリクエストのイベントに対して生成できます。詳細については、「[リクエストトリガーでの HTTP レスポンスを生成する](lambda-generating-http-responses.md#lambda-generating-http-responses-in-requests)」を参照してください。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    /*
     * Generate HTTP redirect response with 302 status code and Location header.
     */
    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html',
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):

    # Generate HTTP redirect response with 302 status code and Location header.

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': 'https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html'
            }]
        }
    }

    return response
```

------

## クエリ文字列 - 例
<a name="lambda-examples-query-string-examples"></a>

以下の例は、クエリ文字列で Lambda@Edge を使用する方法を示しています。

**Topics**
+ [例: クエリ文字列パラメータに基づくヘッダーを追加する](#lambda-examples-header-based-on-query-string)
+ [例: キャッシュヒット率を向上させるためにクエリ文字列パラメータを正規化する](#lambda-examples-normalize-query-string-parameters)
+ [例: 認証されていないユーザーをサインインページにリダイレクトする](#lambda-examples-redirect-to-signin-page)

### 例: クエリ文字列パラメータに基づくヘッダーを追加する
<a name="lambda-examples-header-based-on-query-string"></a>

以下の例では、クエリ文字列パラメータのキーと値のペアを取得してから、それらの値に基づいてヘッダーを追加する方法を示します。

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    
    /* When a request contains a query string key-value pair but the origin server
     * expects the value in a header, you can use this Lambda function to
     * convert the key-value pair to a header. Here's what the function does:
     * 1. Parses the query string and gets the key-value pair.
     * 2. Adds a header to the request using the key-value pair that the function got in step 1.
     */

    /* Parse request querystring to get javascript object */
    const params = querystring.parse(request.querystring);

    /* Move auth param from querystring to headers */
    const headerName = 'Auth-Header';
    request.headers[headerName.toLowerCase()] = [{ key: headerName, value: params.auth }];
    delete params.auth;

    /* Update request querystring */
    request.querystring = querystring.stringify(params);

    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    '''
    When a request contains a query string key-value pair but the origin server
    expects the value in a header, you can use this Lambda function to
    convert the key-value pair to a header. Here's what the function does:
        1. Parses the query string and gets the key-value pair.
        2. Adds a header to the request using the key-value pair that the function got in step 1.
    '''

    # Parse request querystring to get dictionary/json
    params = {k : v[0] for k, v in parse_qs(request['querystring']).items()}

    # Move auth param from querystring to headers
    headerName = 'Auth-Header'
    request['headers'][headerName.lower()] = [{'key': headerName, 'value': params['auth']}]
    del params['auth']

    # Update request querystring
    request['querystring'] = urlencode(params)

    return request
```

------

### 例: キャッシュヒット率を向上させるためにクエリ文字列パラメータを正規化する
<a name="lambda-examples-normalize-query-string-parameters"></a>

次の例では、CloudFront がリクエストをオリジンに転送する前にクエリ文字列に以下の変更を行うことで、キャッシュヒット率を向上させる方法を示します。
+ パラメータの名前によりキーと値のペアをアルファベット順に並べ替える
+ キーと値のペアを小文字に変更する

詳細については、「[クエリ文字列パラメータに基づいてコンテンツをキャッシュする](QueryStringParameters.md)」を参照してください。

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    /* When you configure a distribution to forward query strings to the origin and
     * to cache based on an allowlist of query string parameters, we recommend
     * the following to improve the cache-hit ratio:
     * - Always list parameters in the same order.
     * - Use the same case for parameter names and values.
     *
     * This function normalizes query strings so that parameter names and values
     * are lowercase and parameter names are in alphabetical order.
     *
     * For more information, see:
     * https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html
     */

    console.log('Query String: ', request.querystring);

    /* Parse request query string to get javascript object */
    const params = querystring.parse(request.querystring.toLowerCase());
    const sortedParams = {};

    /* Sort param keys */
    Object.keys(params).sort().forEach(key => {
        sortedParams[key] = params[key];
    });

    /* Update request querystring with normalized  */
    request.querystring = querystring.stringify(sortedParams);

    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    '''
    When you configure a distribution to forward query strings to the origin and
    to cache based on an allowlist of query string parameters, we recommend
    the following to improve the cache-hit ratio:
    Always list parameters in the same order.
    - Use the same case for parameter names and values.

    This function normalizes query strings so that parameter names and values
    are lowercase and parameter names are in alphabetical order.

    For more information, see:
    https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/QueryStringParameters.html
    '''
    print("Query string: ", request["querystring"])

    # Parse request query string to get js object
    params = {k : v[0] for k, v in parse_qs(request['querystring'].lower()).items()}

    # Sort param keys
    sortedParams = sorted(params.items(), key=lambda x: x[0])

    # Update request querystring with normalized
    request['querystring'] = urlencode(sortedParams)
    
    return request
```

------

### 例: 認証されていないユーザーをサインインページにリダイレクトする
<a name="lambda-examples-redirect-to-signin-page"></a>

次の例では、ユーザーが認証情報を入力していない場合にサインインページにリダイレクトする方法を示します。

------
#### [ Node.js ]

```
'use strict';

function parseCookies(headers) {
    const parsedCookie = {};
    if (headers.cookie) {
        headers.cookie[0].value.split(';').forEach((cookie) => {
            if (cookie) {
                const parts = cookie.split('=');
                parsedCookie[parts[0].trim()] = parts[1].trim();
            }
        });
    }
    return parsedCookie;
}

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /* Check for session-id in request cookie in viewer-request event,
     * if session-id is absent, redirect the user to sign in page with original
     * request sent as redirect_url in query params.
     */

    /* Check for session-id in cookie, if present then proceed with request */
    const parsedCookies = parseCookies(headers);
    if (parsedCookies && parsedCookies['session-id']) {
        callback(null, request);
        return;
    }

    /* URI encode the original request to be sent as redirect_url in query params */
    const encodedRedirectUrl = encodeURIComponent(`https://${headers.host[0].value}${request.uri}?${request.querystring}`);
    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: `https://www.example.com/signin?redirect_url=${encodedRedirectUrl}`,
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
import urllib

def parseCookies(headers):
    parsedCookie = {}
    if headers.get('cookie'):
        for cookie in headers['cookie'][0]['value'].split(';'):
            if cookie:
                parts = cookie.split('=')
                parsedCookie[parts[0].strip()] = parts[1].strip()
    return parsedCookie

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Check for session-id in request cookie in viewer-request event,
    if session-id is absent, redirect the user to sign in page with original
    request sent as redirect_url in query params.
    '''

    # Check for session-id in cookie, if present, then proceed with request
    parsedCookies = parseCookies(headers)

    if parsedCookies and parsedCookies['session-id']:
        return request

    # URI encode the original request to be sent as redirect_url in query params
    redirectUrl = "https://%s%s?%s" % (headers['host'][0]['value'], request['uri'], request['querystring'])
    encodedRedirectUrl = urllib.parse.quote_plus(redirectUrl.encode('utf-8'))

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': 'https://www.example.com/signin?redirect_url=%s' % encodedRedirectUrl
            }]
        }
    }
    return response
```

------

## 国またはデバイスタイプヘッダー別のコンテンツのパーソナライズ - 例
<a name="lambda-examples-redirecting-examples"></a>

以下の例は、Lambda@Edge により、ビューワーが使用しているデバイスの場所やタイプに基づいて動作をカスタマイズする方法を示しています。

**Topics**
+ [例: ビューワーリクエストを国に固有の URL にリダイレクトする](#lambda-examples-redirect-based-on-country)
+ [例: デバイスに基づいて異なるバージョンのオブジェクトを供給する](#lambda-examples-vary-on-device-type)

### 例: ビューワーリクエストを国に固有の URL にリダイレクトする
<a name="lambda-examples-redirect-based-on-country"></a>

次の例では、HTTP リダイレクト応答を国に固有の URL で生成し、ビューワーにレスポンスを返す方法を示します。これは、国ごとに異なる応答を提供する場合に便利です。次に例を示します。
+ 国別のサブドメイン (us.example.com および tw.example.com など) がある場合は、ビューワーが example.com をリクエストしたときにリダイレクト応答を生成できます。
+ 動画をストリーミングしていて、そのコンテンツを特定の国でストリーミングする権限がない場合は、その国のユーザーを別のページにリダイレクトして動画を閲覧できない理由について説明できます。

次の点に注意してください。
+ `CloudFront-Viewer-Country` ヘッダーに基づいてキャッシュするようにディストリビューションを設定する必要があります。詳細については、「[選択されたリクエストヘッダーに基づいたキャッシュ](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders)」を参照してください。
+ CloudFront は、ビューワーリクエストイベントの後に `CloudFront-Viewer-Country` ヘッダーを追加します。この例を使用するには、オリジンリクエストイベントのトリガーを作成する必要があります。

------
#### [ Node.js ]

```
'use strict';

/* This is an origin request function */
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /*
     * Based on the value of the CloudFront-Viewer-Country header, generate an
     * HTTP status code 302 (Redirect) response, and return a country-specific
     * URL in the Location header.
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Viewer-Country header. For more information, see
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *       2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    let url = 'https://example.com/';
    if (headers['cloudfront-viewer-country']) {
        const countryCode = headers['cloudfront-viewer-country'][0].value;
        if (countryCode === 'TW') {
            url = 'https://tw.example.com/';
        } else if (countryCode === 'US') {
            url = 'https://us.example.com/';
        }
    }

    const response = {
        status: '302',
        statusDescription: 'Found',
        headers: {
            location: [{
                key: 'Location',
                value: url,
            }],
        },
    };
    callback(null, response);
};
```

------
#### [ Python ]

```
# This is an origin request function

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Based on the value of the CloudFront-Viewer-Country header, generate an
    HTTP status code 302 (Redirect) response, and return a country-specific
    URL in the Location header.
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Viewer-Country header. For more information, see
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
          2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    url = 'https://example.com/'
    viewerCountry = headers.get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        if countryCode == 'TW':
            url = 'https://tw.example.com/'
        elif countryCode == 'US':
            url = 'https://us.example.com/'

    response = {
        'status': '302',
        'statusDescription': 'Found',
        'headers': {
            'location': [{
                'key': 'Location',
                'value': url
            }]
        }
    }

    return response
```

------

### 例: デバイスに基づいて異なるバージョンのオブジェクトを供給する
<a name="lambda-examples-vary-on-device-type"></a>

次の例では、ユーザーが使用しているモバイルデバイスまたはタブレットのようなデバイスのタイプに基づいてオブジェクトの異なるバージョンを提供する方法を示します。次の点に注意してください。
+ `CloudFront-Is-*-Viewer` ヘッダーに基づいてキャッシュするようにディストリビューションを設定する必要があります。詳細については、「[選択されたリクエストヘッダーに基づいたキャッシュ](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders)」を参照してください。
+ CloudFront は、ビューワーリクエストイベントの後に `CloudFront-Is-*-Viewer` ヘッダーを追加します。この例を使用するには、オリジンリクエストイベントのトリガーを作成する必要があります。

------
#### [ Node.js ]

```
'use strict';

/* This is an origin request function */
exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const headers = request.headers;

    /*
     * Serve different versions of an object based on the device type.
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Is-*-Viewer headers. For more information, see
     *          the following documentation:
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type
     *       2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    const desktopPath = '/desktop';
    const mobilePath = '/mobile';
    const tabletPath = '/tablet';
    const smarttvPath = '/smarttv';

    if (headers['cloudfront-is-desktop-viewer']
        && headers['cloudfront-is-desktop-viewer'][0].value === 'true') {
        request.uri = desktopPath + request.uri;
    } else if (headers['cloudfront-is-mobile-viewer']
               && headers['cloudfront-is-mobile-viewer'][0].value === 'true') {
        request.uri = mobilePath + request.uri;
    } else if (headers['cloudfront-is-tablet-viewer']
               && headers['cloudfront-is-tablet-viewer'][0].value === 'true') {
        request.uri = tabletPath + request.uri;
    } else if (headers['cloudfront-is-smarttv-viewer']
               && headers['cloudfront-is-smarttv-viewer'][0].value === 'true') {
        request.uri = smarttvPath + request.uri;
    }
    console.log(`Request uri set to "${request.uri}"`);

    callback(null, request);
};
```

------
#### [ Python ]

```
# This is an origin request function
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    headers = request['headers']

    '''
    Serve different versions of an object based on the device type.
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Is-*-Viewer headers. For more information, see
            the following documentation:
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
            https://docs.aws.amazon.com/console/cloudfront/cache-on-device-type
          2. CloudFront adds the CloudFront-Is-*-Viewer headers after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    desktopPath = '/desktop';
    mobilePath = '/mobile';
    tabletPath = '/tablet';
    smarttvPath = '/smarttv';

    if 'cloudfront-is-desktop-viewer' in headers and headers['cloudfront-is-desktop-viewer'][0]['value'] == 'true':
        request['uri'] = desktopPath + request['uri']
    elif 'cloudfront-is-mobile-viewer' in headers and headers['cloudfront-is-mobile-viewer'][0]['value'] == 'true':
        request['uri'] = mobilePath + request['uri']
    elif 'cloudfront-is-tablet-viewer' in headers and headers['cloudfront-is-tablet-viewer'][0]['value'] == 'true':
        request['uri'] = tabletPath + request['uri']
    elif 'cloudfront-is-smarttv-viewer' in headers and headers['cloudfront-is-smarttv-viewer'][0]['value'] == 'true':
        request['uri'] = smarttvPath + request['uri']

    print("Request uri set to %s" % request['uri'])

    return request
```

------

## コンテンツベースの動的オリジンの選択 - 例
<a name="lambda-examples-content-based-routing-examples"></a>

以下の例は、Lambda@Edge を使用し、リクエスト内の情報に基づいて複数の異なるオリジンにルーティングする方法を示しています。

**Topics**
+ [例: オリジンリクエストトリガーを使用してカスタムオリジンを Amazon S3 オリジンに変更する](#lambda-examples-content-based-S3-origin-based-on-query)
+ [例: オリジンリクエストトリガーを使用して Amazon S3 オリジンのリージョンを変更する](#lambda-examples-content-based-S3-origin-request-trigger)
+ [例: オリジンリクエストトリガーを使用して Amazon S3 オリジンからカスタムオリジンに変更する](#lambda-examples-content-based-custom-origin-request-trigger)
+ [例: オリジンリクエストトリガーを使用して Amazon S3 バケットから別のバケットにトラフィックを徐々に転送する](#lambda-examples-content-based-gradual-traffic-transfer)
+ [例: オリジンリクエストトリガーを使用して Country ヘッダーに基づいてオリジンのドメイン名を変更する](#lambda-examples-content-based-geo-header)

### 例: オリジンリクエストトリガーを使用してカスタムオリジンを Amazon S3 オリジンに変更する
<a name="lambda-examples-content-based-S3-origin-based-on-query"></a>

この関数では、origin-request トリガーを使用して、リクエストのプロパティに基づいて、カスタムオリジンから、コンテンツがフェッチされる Amazon S3 オリジンに変更する方法を示しています。

------
#### [ Node.js ]

```
'use strict';

 const querystring = require('querystring');
 
 exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
 
     /**
      * Reads query string to check if S3 origin should be used, and
      * if true, sets S3 origin properties.
      */
 
     const params = querystring.parse(request.querystring);
 
     if (params['useS3Origin']) {
         if (params['useS3Origin'] === 'true') {
             const s3DomainName = 'amzn-s3-demo-bucket.s3.amazonaws.com';
 
             /* Set S3 origin fields */
             request.origin = {
                 s3: {
                     domainName: s3DomainName,
                     region: '',
                     authMethod: 'origin-access-identity',
                     path: '',
                     customHeaders: {}
                 }
             };
             request.headers['host'] = [{ key: 'host', value: s3DomainName}];
         }
     }
     
    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    '''
    Reads query string to check if S3 origin should be used, and
    if true, sets S3 origin properties
    '''
    params = {k: v[0] for k, v in parse_qs(request['querystring']).items()}
    if params.get('useS3Origin') == 'true':
        s3DomainName = 'amzn-s3-demo-bucket.s3.amazonaws.com'

        # Set S3 origin fields
        request['origin'] = {
            's3': {
                'domainName': s3DomainName,
                'region': '',
                'authMethod': 'origin-access-identity',
                'path': '',
                'customHeaders': {}
            }
        }
        request['headers']['host'] = [{'key': 'host', 'value': s3DomainName}]
    return request
```

------

### 例: オリジンリクエストトリガーを使用して Amazon S3 オリジンのリージョンを変更する
<a name="lambda-examples-content-based-S3-origin-request-trigger"></a>

この関数では、origin-request トリガーを使用して、リクエストのプロパティに基づいて、コンテンツがフェッチされる Amazon S3 オリジンを変更する方法を示しています。

この例では、`CloudFront-Viewer-Country` ヘッダーの値を使用して、S3 バケットのドメイン名を、ビューワーに近いリージョンのバケットに更新します。これは、以下のように役立ちます。
+ 指定したリージョンがビューワーの国に近いほど、レイテンシーが短縮されます。
+ リクエスト元と同じ国にあるオリジンからデータが提供されることになり、データ主権が確保されます。

この例を使用するには、以下を実行する必要があります。
+ `CloudFront-Viewer-Country` ヘッダーに基づいてキャッシュするようにディストリビューションを設定します。詳細については、「[選択されたリクエストヘッダーに基づいたキャッシュ](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders)」を参照してください。
+ オリジンリクエストイベントでこの関数のトリガーを作成します。CloudFront はビューワーリクエストイベントの後に `CloudFront-Viewer-Country` ヘッダーを追加するため、この例を使用するには、オリジンリクエストに対して関数が実行されることを確認する必要があります。

**注記**  
次のコード例では、オリジンに使用しているすべての S3 バケットに同じオリジンアクセスアイデンティティ (OAI) を使用します。詳細については、「[オリジンアクセスアイデンティティ](private-content-restricting-access-to-s3.md#private-content-restricting-access-to-s3-oai)」を参照してください。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    /**
     * This blueprint demonstrates how an origin-request trigger can be used to
     * change the origin from which the content is fetched, based on request properties.
     * In this example, we use the value of the CloudFront-Viewer-Country header
     * to update the S3 bucket domain name to a bucket in a Region that is closer to
     * the viewer.
     * 
     * This can be useful in several ways:
     *      1) Reduces latencies when the Region specified is nearer to the viewer's
     *         country.
     *      2) Provides data sovereignty by making sure that data is served from an
     *         origin that's in the same country that the request came from.
     * 
     * NOTE: 1. You must configure your distribution to cache based on the
     *          CloudFront-Viewer-Country header. For more information, see
     *          https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
     *       2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
     *          request event. To use this example, you must create a trigger for the
     *          origin request event.
     */

    const countryToRegion = {
        'DE': 'eu-central-1',
        'IE': 'eu-west-1',
        'GB': 'eu-west-2',
        'FR': 'eu-west-3',
        'JP': 'ap-northeast-1',
        'IN': 'ap-south-1'
    };

    if (request.headers['cloudfront-viewer-country']) {
        const countryCode = request.headers['cloudfront-viewer-country'][0].value;
        const region = countryToRegion[countryCode];
        
        /**
         * If the viewer's country is not in the list you specify, the request
         * goes to the default S3 bucket you've configured.
         */  
        if (region) {
            /**
             * If you've set up OAI, the bucket policy in the destination bucket
             * should allow the OAI GetObject operation, as configured by default
             * for an S3 origin with OAI. Another requirement with OAI is to provide
             * the Region so it can be used for the SIGV4 signature. Otherwise, the
             * Region is not required.
             */
            request.origin.s3.region = region;
            const domainName = `amzn-s3-demo-bucket-in-${region}.s3.${region}.amazonaws.com`;
            request.origin.s3.domainName = domainName;
            request.headers['host'] = [{ key: 'host', value: domainName }];
        }
    }

    callback(null, request);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    '''
    This blueprint demonstrates how an origin-request trigger can be used to
    change the origin from which the content is fetched, based on request properties.
    In this example, we use the value of the CloudFront-Viewer-Country header
    to update the S3 bucket domain name to a bucket in a Region that is closer to
    the viewer.
    
    This can be useful in several ways:
        1) Reduces latencies when the Region specified is nearer to the viewer's
            country.
        2) Provides data sovereignty by making sure that data is served from an
            origin that's in the same country that the request came from.
    
    NOTE: 1. You must configure your distribution to cache based on the
            CloudFront-Viewer-Country header. For more information, see
            https://docs.aws.amazon.com/console/cloudfront/cache-on-selected-headers
          2. CloudFront adds the CloudFront-Viewer-Country header after the viewer
            request event. To use this example, you must create a trigger for the
            origin request event.
    '''

    countryToRegion = {
        'DE': 'eu-central-1',
        'IE': 'eu-west-1',
        'GB': 'eu-west-2',
        'FR': 'eu-west-3',
        'JP': 'ap-northeast-1',
        'IN': 'ap-south-1'
    }

    viewerCountry = request['headers'].get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        region = countryToRegion.get(countryCode)

        # If the viewer's country in not in the list you specify, the request
        # goes to the default S3 bucket you've configured
        if region:
            '''
            If you've set up OAI, the bucket policy in the destination bucket
            should allow the OAI GetObject operation, as configured by default
            for an S3 origin with OAI. Another requirement with OAI is to provide
            the Region so it can be used for the SIGV4 signature. Otherwise, the
            Region is not required.
            '''
            request['origin']['s3']['region'] = region
            domainName = 'amzn-s3-demo-bucket-in-{0}.s3.{0}.amazonaws.com'.format(region)
            request['origin']['s3']['domainName'] = domainName
            request['headers']['host'] = [{'key': 'host', 'value': domainName}]

    return request
```

------

### 例: オリジンリクエストトリガーを使用して Amazon S3 オリジンからカスタムオリジンに変更する
<a name="lambda-examples-content-based-custom-origin-request-trigger"></a>

この関数では、origin-request トリガーを使用して、リクエストのプロパティに基づいて、コンテンツがフェッチされるカスタムオリジンを変更する方法を示しています。

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');
 
 exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
 
     /**
      * Reads query string to check if custom origin should be used, and
      * if true, sets custom origin properties.
      */
 
     const params = querystring.parse(request.querystring);
 
     if (params['useCustomOrigin']) {
         if (params['useCustomOrigin'] === 'true') {
 
             /* Set custom origin fields*/
             request.origin = {
                 custom: {
                     domainName: 'www.example.com',
                     port: 443,
                     protocol: 'https',
                     path: '',
                     sslProtocols: ['TLSv1', 'TLSv1.1'],
                     readTimeout: 5,
                     keepaliveTimeout: 5,
                     customHeaders: {}
                 }
             };
             request.headers['host'] = [{ key: 'host', value: 'www.example.com'}];
         }
     }
    callback(null, request);
};
```

------
#### [ Python ]

```
from urllib.parse import parse_qs

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    # Reads query string to check if custom origin should be used, and
    # if true, sets custom origin properties

    params = {k: v[0] for k, v in parse_qs(request['querystring']).items()}

    if params.get('useCustomOrigin') == 'true':
            # Set custom origin fields
            request['origin'] = {
                'custom': {
                    'domainName': 'www.example.com',
                    'port': 443,
                    'protocol': 'https',
                    'path': '',
                    'sslProtocols': ['TLSv1', 'TLSv1.1'],
                    'readTimeout': 5,
                    'keepaliveTimeout': 5,
                    'customHeaders': {}
                }
            }
            request['headers']['host'] = [{'key': 'host', 'value': 'www.example.com'}]

    return request
```

------

### 例: オリジンリクエストトリガーを使用して Amazon S3 バケットから別のバケットにトラフィックを徐々に転送する
<a name="lambda-examples-content-based-gradual-traffic-transfer"></a>

この関数では、Amazon S3 バケットから別のバケットにトラフィックを制御しながら徐々に転送する方法を示しています。

------
#### [ Node.js ]

```
'use strict';

    function getRandomInt(min, max) {
        /* Random number is inclusive of min and max*/
        return Math.floor(Math.random() * (max - min + 1)) + min;
 }

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;
    const BLUE_TRAFFIC_PERCENTAGE = 80;

    /**
      * This Lambda function demonstrates how to gradually transfer traffic from
      * one S3 bucket to another in a controlled way.
      * We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from
      * 1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic
      * is re-directed to blue-bucket. If not, the default bucket that we've configured
      * is used.
      */

    const randomNumber = getRandomInt(1, 100);

if (randomNumber <= BLUE_TRAFFIC_PERCENTAGE) {
         const domainName = 'blue-bucket.s3.amazonaws.com';
         request.origin.s3.domainName = domainName;
         request.headers['host'] = [{ key: 'host', value: domainName}];
     }
    callback(null, request);
};
```

------
#### [ Python ]

```
import math
import random

def getRandomInt(min, max):
    # Random number is inclusive of min and max
    return math.floor(random.random() * (max - min + 1)) + min

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    BLUE_TRAFFIC_PERCENTAGE = 80

    '''
    This Lambda function demonstrates how to gradually transfer traffic from
    one S3 bucket to another in a controlled way.
    We define a variable BLUE_TRAFFIC_PERCENTAGE which can take values from
    1 to 100. If the generated randomNumber less than or equal to BLUE_TRAFFIC_PERCENTAGE, traffic
    is re-directed to blue-bucket. If not, the default bucket that we've configured
    is used.
    '''

    randomNumber = getRandomInt(1, 100)

    if randomNumber <= BLUE_TRAFFIC_PERCENTAGE:
        domainName = 'blue-bucket.s3.amazonaws.com'
        request['origin']['s3']['domainName'] = domainName
        request['headers']['host'] = [{'key': 'host', 'value': domainName}]

    return request
```

------

### 例: オリジンリクエストトリガーを使用して Country ヘッダーに基づいてオリジンのドメイン名を変更する
<a name="lambda-examples-content-based-geo-header"></a>

この関数では、`CloudFront-Viewer-Country` ヘッダーに基づいてオリジンのドメイン名を変更する方法を示しています。これにより、コンテンツはビューワーの国に近いオリジンから配信されます。

ディストリビューションに対してこの機能を実装すると、次のような利点があります。
+ 指定したリージョンがビューワーの国に近いほど、レイテンシーが短縮されます。
+ リクエスト元と同じ国にあるオリジンからデータが提供されることになり、データ主権が確保されます。

この機能を有効にするには、`CloudFront-Viewer-Country` ヘッダーに基づいてキャッシュするようにディストリビューションを設定する必要があります。詳細については、「[選択されたリクエストヘッダーに基づいたキャッシュ](DownloadDistValuesCacheBehavior.md#DownloadDistValuesForwardHeaders)」を参照してください。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
     const request = event.Records[0].cf.request;
     
  if (request.headers['cloudfront-viewer-country']) {
         const countryCode = request.headers['cloudfront-viewer-country'][0].value;
         if (countryCode === 'GB' || countryCode === 'DE' || countryCode === 'IE' ) {
             const domainName = 'eu.example.com';
             request.origin.custom.domainName = domainName;
             request.headers['host'] = [{key: 'host', value: domainName}];
         } 
     }
     
    callback(null, request);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    viewerCountry = request['headers'].get('cloudfront-viewer-country')
    if viewerCountry:
        countryCode = viewerCountry[0]['value']
        if countryCode == 'GB' or countryCode == 'DE' or countryCode == 'IE':
            domainName = 'eu.example.com'
            request['origin']['custom']['domainName'] = domainName
            request['headers']['host'] = [{'key': 'host', 'value': domainName}]
    return request
```

------

## エラーステータスを更新する - 例
<a name="lambda-examples-update-error-status-examples"></a>

以下の例は、Lambda@Edge を使用して、ユーザーに返すエラーステータスを変更する方法を示しています。

**Topics**
+ [例: オリジンレスポンストリガーを使用してエラーステータスコードを 200 に更新する](#lambda-examples-custom-error-static-body)
+ [例: オリジンレスポンストリガーを使用してエラーステータスコードを 302 に更新する](#lambda-examples-custom-error-new-site)

### 例: オリジンレスポンストリガーを使用してエラーステータスコードを 200 に更新する
<a name="lambda-examples-custom-error-static-body"></a>

この関数では、レスポンスステータスを 200 に更新し、以下のシナリオでビューワーに返す静的な本文コンテンツを生成する方法を示しています。
+ 関数がオリジンレスポンスでトリガーされる。
+ オリジンサーバーからのレスポンスステータスがエラーステータスコード (4xx または 5xx) である。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;

    /**
     * This function updates the response status to 200 and generates static
     * body content to return to the viewer in the following scenario:
     * 1. The function is triggered in an origin response
     * 2. The response status from the origin server is an error status code (4xx or 5xx)
     */

    if (response.status >= 400 && response.status <= 599) {
        response.status = 200;
        response.statusDescription = 'OK';
        response.body = 'Body generation example';
    }

    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']

    '''
    This function updates the response status to 200 and generates static
    body content to return to the viewer in the following scenario:
    1. The function is triggered in an origin response
    2. The response status from the origin server is an error status code (4xx or 5xx)
    '''

    if int(response['status']) >= 400 and int(response['status']) <= 599:
        response['status'] = 200
        response['statusDescription'] = 'OK'
        response['body'] = 'Body generation example'
    return response
```

------

### 例: オリジンレスポンストリガーを使用してエラーステータスコードを 302 に更新する
<a name="lambda-examples-custom-error-new-site"></a>

この関数では、HTTP ステータスコードを 302 に更新して、異なるオリジンを設定した別のパス (キャッシュ動作) にリダイレクトする方法を示しています。次の点に注意してください。
+ 関数がオリジンレスポンスでトリガーされる。
+ オリジンサーバーからのレスポンスステータスがエラーステータスコード (4xx または 5xx) である。

------
#### [ Node.js ]

```
'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;
    const request = event.Records[0].cf.request;

    /**
     * This function updates the HTTP status code in the response to 302, to redirect to another
     * path (cache behavior) that has a different origin configured. Note the following:
     * 1. The function is triggered in an origin response
     * 2. The response status from the origin server is an error status code (4xx or 5xx)
     */

    if (response.status >= 400 && response.status <= 599) {
        const redirect_path = `/plan-b/path?${request.querystring}`;

        response.status = 302;
        response.statusDescription = 'Found';

        /* Drop the body, as it is not required for redirects */
        response.body = '';
        response.headers['location'] = [{ key: 'Location', value: redirect_path }];
    }

    callback(null, response);
};
```

------
#### [ Python ]

```
def lambda_handler(event, context):
    response = event['Records'][0]['cf']['response']
    request = event['Records'][0]['cf']['request']

    '''
    This function updates the HTTP status code in the response to 302, to redirect to another
    path (cache behavior) that has a different origin configured. Note the following:
    1. The function is triggered in an origin response
    2. The response status from the origin server is an error status code (4xx or 5xx)
    '''

    if int(response['status']) >= 400 and int(response['status']) <= 599:
        redirect_path = '/plan-b/path?%s' % request['querystring']

        response['status'] = 302
        response['statusDescription'] = 'Found'

        # Drop the body as it is not required for redirects
        response['body'] = ''
        response['headers']['location'] = [{'key': 'Location', 'value': redirect_path}]

    return response
```

------

## リクエストボディにアクセスする - 例
<a name="lambda-examples-access-request-body-examples"></a>

以下の例は、Lambda@Edge を使用して POST リクエストを操作する方法を示しています。

**注記**  
これらの例を使用するには、ディストリビューションの Lambda 関数の関連付けで *[Include body]* (ボディを含める) オプションを有効にする必要があります。デフォルトでは、有効になっていません。  
CloudFront コンソールでこの設定を有効にするには、[**Lambda 関数の関連付け**] の [**ボディを含める**] チェックボックスをオンにします。
CloudFront API または CloudFormation でこの設定を有効にするには、`LambdaFunctionAssociation` の `IncludeBody` フィールドを `true` に設定します。

**Topics**
+ [例: リクエストトリガーを使用して HTML フォームを読み込む](#lambda-examples-access-request-body-examples-read)
+ [例: リクエストトリガーを使用して HTML フォームを変更する](#lambda-examples-access-request-body-examples-replace)

### 例: リクエストトリガーを使用して HTML フォームを読み込む
<a name="lambda-examples-access-request-body-examples-read"></a>

この関数では、「お問い合わせ」フォームなど HTML フォーム (ウェブフォーム) によって生成された POST リクエストボディを処理する方法を示しています。たとえば、次のような HTML フォームがあります。

```
<html>
  <form action="https://example.com" method="post">
    Param 1: <input type="text" name="name1"><br>
    Param 2: <input type="text" name="name2"><br>
    input type="submit" value="Submit">
  </form>
</html>
```

次の関数の例では、関数は CloudFront ビューワーリクエストまたはオリジンリクエストでトリガーされる必要があります。

------
#### [ Node.js ]

```
'use strict';

const querystring = require('querystring');

/**
 * This function demonstrates how you can read the body of a POST request 
 * generated by an HTML form (web form). The function is triggered in a
 * CloudFront viewer request or origin request event type.
 */

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    if (request.method === 'POST') {
        /* HTTP body is always passed as base64-encoded string. Decode it. */
        const body = Buffer.from(request.body.data, 'base64').toString();
 
        /* HTML forms send the data in query string format. Parse it. */
        const params = querystring.parse(body);
 
        /* For demonstration purposes, we only log the form fields here.
         * You can put your custom logic here. For example, you can store the 
         * fields in a database, such as Amazon DynamoDB, and generate a response
         * right from your Lambda@Edge function.
         */
        for (let param in params) {
            console.log(`For "${param}" user submitted "${params[param]}".\n`);
        }
    }
    return callback(null, request);
};
```

------
#### [ Python ]

```
import base64
from urllib.parse import parse_qs

'''
Say there is a POST request body generated by an HTML such as:

<html>
<form action="https://example.com" method="post">
    Param 1: <input type="text" name="name1"><br>
    Param 2: <input type="text" name="name2"><br>
    input type="submit" value="Submit">
</form>
</html>

'''

'''
This function demonstrates how you can read the body of a POST request 
generated by an HTML form (web form). The function is triggered in a
CloudFront viewer request or origin request event type.
'''

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']

    if request['method'] == 'POST':
        # HTTP body is always passed as base64-encoded string. Decode it
        body = base64.b64decode(request['body']['data'])

        # HTML forms send the data in query string format. Parse it
        params = {k: v[0] for k, v in parse_qs(body).items()}

        '''
        For demonstration purposes, we only log the form fields here.
        You can put your custom logic here. For example, you can store the
        fields in a database, such as Amazon DynamoDB, and generate a response
        right from your Lambda@Edge function.
        '''
        for key, value in params.items():
            print("For %s use submitted %s" % (key, value))
            
    return request
```

------

### 例: リクエストトリガーを使用して HTML フォームを変更する
<a name="lambda-examples-access-request-body-examples-replace"></a>

この関数では、HTML フォーム (ウェブフォーム) によって生成された POST リクエストボディを変更する方法を示しています。この関数は、CloudFront ビューワーリクエストまたはオリジンリクエストでトリガーされます。

------
#### [ Node.js ]

```
'use strict';
				
const querystring = require('querystring');

exports.handler = (event, context, callback) => {
    var request = event.Records[0].cf.request;
    if (request.method === 'POST') {
        /* Request body is being replaced. To do this, update the following
        /* three fields:
         *    1) body.action to 'replace'
         *    2) body.encoding to the encoding of the new data.
         *
         *       Set to one of the following values:
         *
         *           text - denotes that the generated body is in text format.
         *               Lambda@Edge will propagate this as is.
         *           base64 - denotes that the generated body is base64 encoded.
         *               Lambda@Edge will base64 decode the data before sending
         *               it to the origin.
         *    3) body.data to the new body.
         */
        request.body.action = 'replace';
        request.body.encoding = 'text';
        request.body.data = getUpdatedBody(request);
    }
    callback(null, request);
};

function getUpdatedBody(request) {
    /* HTTP body is always passed as base64-encoded string. Decode it. */
    const body = Buffer.from(request.body.data, 'base64').toString();

    /* HTML forms send data in query string format. Parse it. */
    const params = querystring.parse(body);

    /* For demonstration purposes, we're adding one more param.
     *
     * You can put your custom logic here. For example, you can truncate long
     * bodies from malicious requests.
     */
    params['new-param-name'] = 'new-param-value';
    return querystring.stringify(params);
}
```

------
#### [ Python ]

```
import base64
from urllib.parse import parse_qs, urlencode

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request']
    if request['method'] == 'POST':
        '''
        Request body is being replaced. To do this, update the following
        three fields:
            1) body.action to 'replace'
            2) body.encoding to the encoding of the new data.
        
            Set to one of the following values:
        
                text - denotes that the generated body is in text format.
                    Lambda@Edge will propagate this as is.
                base64 - denotes that the generated body is base64 encoded.
                    Lambda@Edge will base64 decode the data before sending
                    it to the origin.
            3) body.data to the new body.
        '''
        request['body']['action'] = 'replace'
        request['body']['encoding'] = 'text'
        request['body']['data'] = getUpdatedBody(request)
    return request

def getUpdatedBody(request):
    # HTTP body is always passed as base64-encoded string. Decode it
    body = base64.b64decode(request['body']['data'])

    # HTML forms send data in query string format. Parse it
    params = {k: v[0] for k, v in parse_qs(body).items()}

    # For demonstration purposes, we're adding one more param

    # You can put your custom logic here. For example, you can truncate long
    # bodies from malicious requests
    params['new-param-name'] = 'new-param-value'
    return urlencode(params)
```

------

# エッジ関数に対する制限
<a name="edge-functions-restrictions"></a>

以下のトピックでは、CloudFront Functions と Lambda@Edge に適用される制限について説明します。制限には、すべてのエッジ関数に適用されるものもあれば、CloudFront Functions または Lambda@Edge のみに適用されるものもあります。

各トピックでは、CloudFront でエッジ関数を開発してデプロイする際に考慮すべき制限と制約についての詳細が提供されます。

このような制限を把握しておくと、エッジ関数が期待どおりに動作し、サポートされる機能に準拠していることを確認できます。

**Topics**
+ [すべてのエッジ機能に対する制限](edge-function-restrictions-all.md)
+ [CloudFront Functions に対する制限](cloudfront-function-restrictions.md)
+ [Lambda@Edge に対する制限](lambda-at-edge-function-restrictions.md)

クォータ (以前は制限と呼ばれていました) の詳細については、「[CloudFront Functions のクォータ](cloudfront-limits.md#limits-functions)」と「[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)」を参照してください。

# すべてのエッジ機能に対する制限
<a name="edge-function-restrictions-all"></a>

以下の制限は、CloudFront Functions と Lambda@Edge 両方の、すべてのエッジ関数に適用されます。

**Topics**
+ [AWS アカウント の所有権](#function-restrictions-account-ownership)
+ [CloudFront Functions と Lambda@Edge との組み合わせ](#function-restrictions-combining-functions)
+ [HTTP ステータスコード](#function-restrictions-status-codes)
+ [HTTP ヘッダー](#function-restrictions-headers)
+ [クエリ文字列](#function-restrictions-query-strings)
+ [[URI]](#function-restrictions-uri)
+ [URI、クエリ文字列、ヘッダーのエンコーディング](#function-restrictions-encoding)
+ [Microsoft Smooth Streaming](#function-restrictions-microsoft-smooth-streaming)
+ [タグ付け](#function-restrictions-tagging)

## AWS アカウント の所有権
<a name="function-restrictions-account-ownership"></a>

エッジ関数を CloudFront ディストリビューションに関連付けるには、関数とディストリビューションが同じ AWS アカウント によって所有されている必要があります。

## CloudFront Functions と Lambda@Edge との組み合わせ
<a name="function-restrictions-combining-functions"></a>

所定のキャッシュ動作については、以下の制限が適用されます。
+ イベントタイプ (ビューワーリクエスト、オリジンリクエスト、オリジンレスポンス、ビューワーレスポンス) はそれぞれ、エッジ関数の関連付けを 1 つしか持てません。
+ ビューワーイベント (ビューワーリクエストとビューワーレスポンス) で CloudFront Functions と Lambda@Edge を組み合わせることはできません。

上記以外のすべてのエッジ関数の組み合わせが許可されます。以下の表は、許可される組み合わせの説明です。

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/edge-function-restrictions-all.html)

## HTTP ステータスコード
<a name="function-restrictions-status-codes"></a>

オリジンが 400 以上の HTTP ステータスコードを返す場合、CloudFront はビューワーレスポンスイベントのエッジ関数を呼び出しません。

オリジンレスポンスイベントの Lambda@Edge 関数は、オリジンが 400 以上の HTTP ステータスコードを返す場合を含め、*すべて*のオリジンレスポンスに対して呼び出されます。詳細については、「[オリジンレスポンストリガーでの HTTP レスポンスを更新する](lambda-generating-http-responses.md#lambda-updating-http-responses)」を参照してください。

## HTTP ヘッダー
<a name="function-restrictions-headers"></a>

特定の HTTP ヘッダーは許可されていません。これは、これらのヘッダーがエッジ関数に公開されておらず、関数がそれらを追加できないことを意味します。他のヘッダーは読み取り専用であるため、関数で読み取ることはできますが、追加や変更はできません。

**Topics**
+ [許可されていないヘッダー](#function-restrictions-disallowed-headers)
+ [読み取り専用ヘッダー](#function-restrictions-read-only-headers)

### 許可されていないヘッダー
<a name="function-restrictions-disallowed-headers"></a>

以下の HTTP ヘッダーはエッジ関数に公開されておらず、関数はこれらを追加できません。関数がこれらのヘッダーのいずれかを追加すると、CloudFront 検証が失敗し、CloudFront がビューワーに HTTP ステータスコード 502 (不正なゲートウェイ) を返します。
+ `Connection` 
+ `Expect`
+ `Keep-Alive`
+ `Proxy-Authenticate`
+ `Proxy-Authorization`
+ `Proxy-Connection`
+ `Trailer`
+ `Upgrade`
+ `X-Accel-Buffering`
+ `X-Accel-Charset`
+ `X-Accel-Limit-Rate`
+ `X-Accel-Redirect`
+ `X-Amz-Cf-*`
+ `X-Amzn-Auth`
+ `X-Amzn-Cf-Billing`
+ `X-Amzn-Cf-Id`
+ `X-Amzn-Cf-Xff`
+ `X-Amzn-Errortype`
+ `X-Amzn-Fle-Profile`
+ `X-Amzn-Header-Count`
+ `X-Amzn-Header-Order`
+ `X-Amzn-Lambda-Integration-Tag`
+ `X-Amzn-RequestId`
+ `X-Cache`
+ `X-Edge-*`
+ `X-Forwarded-Proto`
+ `X-Real-IP`

### 読み取り専用ヘッダー
<a name="function-restrictions-read-only-headers"></a>

以下のヘッダーは読み取り専用です。関数はこれらを読み取って関数ロジックへの入力として使用できますが、値を変更することはできません。関数が読み取り専用ヘッダーを追加または編集すると、リクエストの CloudFront 検証が失敗し、CloudFront がビューワーに HTTP ステータスコード 502 (不正なゲートウェイ) を返します。

#### ビューワーリクエストイベントの読み取り専用ヘッダー
<a name="function-restrictions-read-only-headers-viewer-request"></a>

以下のヘッダーは、ビューワーリクエストイベントでは読み取り専用になります。
+ `Content-Length`
+ `Host`
+ `Transfer-Encoding`
+ `Via`

#### オリジンリクエストイベントの読み取り専用ヘッダー (Lambda@Edge 限定)
<a name="function-restrictions-read-only-headers-origin-request"></a>

以下のヘッダーは、Lambda@Edge にしかないオリジンリクエストイベントでは読み取り専用になります。
+ `Accept-Encoding`
+ `Content-Length`
+ `If-Modified-Since`
+ `If-None-Match`
+ `If-Range`
+ `If-Unmodified-Since`
+ `Transfer-Encoding`
+ `Via`

#### オリジンレスポンスイベントの読み取り専用ヘッダー (Lambda@Edge 限定)
<a name="function-restrictions-read-only-headers-origin-response"></a>

以下のヘッダーは、Lambda@Edge にしかないオリジンレスポンスイベントでは読み取り専用になります。
+ `Transfer-Encoding`
+ `Via`

#### ビューワーレスポンスイベントの読み取り専用ヘッダー
<a name="function-restrictions-read-only-headers-viewer-response"></a>

以下のヘッダーは、CloudFront Functions と Lambda@Edge の両方のビューワーレスポンスイベントでは読み取り専用になります。
+ `Warning`
+ `Via`

以下のヘッダーは、Lambda@Edge のビューワーレスポンスイベントでは読み取り専用になります。
+ `Content-Length`
+ `Content-Encoding`
+ `Transfer-Encoding`

## クエリ文字列
<a name="function-restrictions-query-strings"></a>

以下の制限は、リクエスト URI 内のクエリ文字列を読み取る、更新する、または作成する関数に適用されます。
+ (Lambda@Edge 限定) オリジンリクエストまたはオリジンレスポンス関数のクエリ文字列にアクセスするには、キャッシュポリシーまたはオリジンリクエストポリシーが [**Query strings**] (クエリ文字列) に対して [**All**] (すべて) に設定されている必要があります。
+ 関数は、ビューワーリクエストイベントとオリジンリクエストイベントのクエリ文字列を作成または更新できます (オリジンリクエストイベントがあるのは Lambda@Edge だけです)。
+ 関数は、オリジンレスポンスイベントとビューワーレスポンスイベントのクエリ文字列を読み取ることができますが、それらを作成または更新することはできません (オリジンレスポンスイベントがあるのは Lambda@Edge だけです)。
+ 関数がクエリ文字列を作成または更新する場合は、以下の制限が適用されます。
  + クエリ文字列に、スペース、制御文字、またはフラグメント識別子 (`#`) を含めることはできません。
  + クエリ文字列を含めた URI の合計サイズは、8,192 文字未満にする必要があります。
  + URI およびクエリ文字列には、パーセントエンコーディングを使用することをお勧めします。詳細については、「[URI、クエリ文字列、ヘッダーのエンコーディング](#function-restrictions-encoding)」を参照してください。

## [URI]
<a name="function-restrictions-uri"></a>

関数でリクエストの URI を変更しても、リクエストのキャッシュ動作や転送先オリジンは変わりません。

クエリ文字列を含めた URI の合計サイズは、8,192 文字未満にする必要があります。

## URI、クエリ文字列、ヘッダーのエンコーディング
<a name="function-restrictions-encoding"></a>

エッジ関数に渡される URI、クエリ文字列、ヘッダーの値は、UTF-8 でエンコードされています。関数は、それが返す URI、クエリ文字列、ヘッダーの値に UTF-8 エンコーディングを使用する必要があります。パーセントエンコーディングには、UTF-8 エンコーディングと互換性があります。

以下のリストでは、CloudFront が URI、クエリ文字列、ヘッダーのエンコーディングをどのように処理するかを説明します。
+ リクエスト内の値が UTF-8 でエンコードされている場合、CloudFront はそれらの値を変更せずにそのまま関数に転送します。
+ リクエスト内の値が [ISO 8859-1 でエンコード](https://en.wikipedia.org/wiki/ISO/IEC_8859-1)されている場合、CloudFront はそれらの値を UTF-8 エンコーディングに変換してから関数に転送します。
+ リクエスト内の値がその他の文字エンコーディングを使用してエンコードされている場合、CloudFront はそれらが ISO 8859-1 でエンコードされているとみなし、ISO 8859-1 から UTF-8 への変換を試みます。
**重要**  
変換された文字は、元のリクエストの値の正しい解釈ではない可能性があります。これは、関数またはオリジンが意図しない結果を生成する原因になる場合があります。

CloudFront がオリジンに転送する URI、クエリ文字列、ヘッダーは、関数がそれらの値を変更するかどうかに応じて異なります。
+ 関数が URI、クエリ文字列、またはヘッダーを変更しない場合、CloudFront はリクエストで受け取った値をオリジンに転送します。
+ 関数が URI、クエリ文字列、またはヘッダーを変更する場合、CloudFront は UTF-8 でエンコードされた値を転送します。

## Microsoft Smooth Streaming
<a name="function-restrictions-microsoft-smooth-streaming"></a>

Microsoft Smooth Streaming 形式にトランスコードしたメディアファイルのストリーミングに使用している CloudFront ディストリビューションでは、エッジ関数を使用できません。

## タグ付け
<a name="function-restrictions-tagging"></a>

エッジ関数にタグを追加することはできません。CloudFront でのタグ付けの詳細については、「[ディストリビューションのタグ付け](tagging.md)」を参照してください。

# CloudFront Functions に対する制限
<a name="cloudfront-function-restrictions"></a>

以下の制限は、CloudFront Functions のみに適用されます。

**Contents**
+ [ログ](#cloudfront-function-restrictions-logs)
+ [リクエストボディ](#cloudfront-function-restrictions-request-body)
+ [CloudFront KeyValueStore API での一時的な認証情報の使用](#regional-endpoint-for-key-value-store)
+ [ランタイム](#cloudfront-function-runtime-restrictions)
+ [コンピューティング使用率](#cloudfront-function-restrictions-compute-utilization)

クォータ (以前は制限と呼ばれていました) の詳細については、「[CloudFront Functions のクォータ](cloudfront-limits.md#limits-functions)」を参照してください。

## ログ
<a name="cloudfront-function-restrictions-logs"></a>

CloudFront Functions の関数ログは 10 KB で切り捨てられます。

## リクエストボディ
<a name="cloudfront-function-restrictions-request-body"></a>

CloudFront Functions は、HTTP リクエストのボディにアクセスできません。

## CloudFront KeyValueStore API での一時的な認証情報の使用
<a name="regional-endpoint-for-key-value-store"></a>

AWS Security Token Service (AWS STS) を使用して、一時的なセキュリティ認証情報 (セッショントークンとも呼ばれる) を生成できます。**セッショントークンを使用すると、AWS Identity and Access Management (IAM) ロールを一時的に引き受けて、AWS のサービス にアクセスできます。

[CloudFront KeyValueStore API](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_Operations_Amazon_CloudFront_KeyValueStore.html) を呼び出すには、AWS STS でリージョンのエンドポイントを使用して、Version 2 のセッショントークンを返します。****AWS STS (`sts.amazonaws.com`) のグローバルエンドポイントを使用する場合、AWS STS は、Signature Version 4A (SigV4A) ではサポートされていない Version 1 セッショントークンを生成します。****その結果、認証エラーが発生します。

CloudFront KeyValueStore API を呼び出すために使用できるオプション: 

**AWS CLI と AWS SDK**  
AWS CLI または AWS SDKを設定すると、リージョンの AWS STS エンドポイントを使用できます。詳細については、「AWS SDK とツールリファレンスガイド」の「[AWS STS リージョンエンドポイント](https://docs.aws.amazon.com/sdkref/latest/guide/feature-sts-regionalized-endpoints.html)」を参照してください。**  
利用可能な AWS STS エンドポイントの詳細については、「**IAM ユーザーガイド」の「[リージョンとエンドポイント](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html#id_credentials_region-endpoints)」を参照してください。

**SAML**  
リージョンの AWS STS エンドポイントを使用するように SAML を設定できます。詳細については、ブログ記事「[フェイルオーバーにリージョン SAML エンドポイントを使用する方法](https://aws.amazon.com/blogs/security/how-to-use-regional-saml-endpoints-for-failover/)」を参照してください。

**`SetSecurityTokenServicePreferences` API**  
リージョンの AWS STS エンドポイントを使用する代わりに、AWS STS のグローバルエンドポイントを設定して Version 2 セッショントークンを返すことができます。これを行うには、[SetSecurityTokenServicePreferences](https://docs.aws.amazon.com/IAM/latest/APIReference/API_SetSecurityTokenServicePreferences.html) API オペレーションを使用して、AWS アカウント を設定します。  

**Example 例: IAM CLI コマンド**  

```
aws iam set-security-token-service-preferences --global-endpoint-token-version v2Token
```
このオプションの代わりに、AWS STS リージョンエンドポイントを使用することをお勧めします。リージョンエンドポイントを使用すると、可用性とフェイルオーバーシナリオが向上します。

**カスタム ID プロバイダー**  
フェデレーションを行い、ロールを引き受けるカスタム ID プロバイダーを使用している場合は、セッショントークンの生成を担当する親 ID プロバイダーシステムの前述のオプションのいずれかを使用します。

## ランタイム
<a name="cloudfront-function-runtime-restrictions"></a>

CloudFront Functions のランタイム環境は、動的コード評価をサポートしておらず、ネットワーク、ファイルシステム、タイマーへのアクセスを制限します。詳細については、「[制限された機能](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features)」を参照してください。

**注記**  
CloudFront KeyValueStore を使用するには、CloudFront 関数で [JavaScript ランタイム 2.0](functions-javascript-runtime-20.md) を使用する必要があります。

## コンピューティング使用率
<a name="cloudfront-function-restrictions-compute-utilization"></a>

CloudFront Functions には実行に使用できる時間に対する制限があり、これは*コンピューティング使用率*として測定されます。コンピューティング使用率は、関数の実行にかかった時間を最大許容時間に対する割合として示す 0 から 100 の数値です。例えば、コンピューティング使用率が 35 の場合、関数は最大許容時間の 35% で完了したことを意味します。

[関数をテストする](test-function.md)ときは、テストイベントの出力でコンピューティング使用率の値を確認できます。production 関数については、CloudWatch、または [CloudFront コンソールの [Monitoring] (モニタリング) ページ](https://console.aws.amazon.com/cloudfront/v4/home?#/monitoring)で[コンピューティング使用率メトリクス](viewing-cloudfront-metrics.md#monitoring-console.cloudfront-functions)を確認できます。

# Lambda@Edge に対する制限
<a name="lambda-at-edge-function-restrictions"></a>

以下の制限は、Lambda@Edge のみに適用されます。

**Contents**
+ [DNS 解決](#lambda-at-edge-restrictions-dns)
+ [HTTP ステータスコード](#lambda-at-edge-restrictions-status-codes)
+ [Lambda 関数のバージョン](#lambda-at-edge-restrictions-version)
+ [Lambda リージョン](#lambda-at-edge-restrictions-region)
+ [Lambda のロール許可](#lambda-at-edge-restrictions-role-permissions)
+ [Lambda の機能](#lambda-at-edge-restrictions-features)
+ [ランタイムのサポート](#lambda-at-edge-restrictions-runtime)
+ [CloudFront ヘッダー](#lambda-at-edge-restrictions-cloudfront-headers)
+ [[本文を含める] オプションを使用する場合のリクエスト本文に対する制限](#lambda-at-edge-restrictions-request-body)
+ [レスポンスタイムアウトとキープアライブタイムアウト (カスタムオリジンのみ)](#timeout-for-lambda-edge-functions)

 クォータの詳細については、「」を参照してください[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)

## DNS 解決
<a name="lambda-at-edge-restrictions-dns"></a>

CloudFront は、オリジンドメイン名で DNS 解決を実行してから、オリジンリクエストの Lambda@Edge 関数を実行します。**ドメインの DNS サービスで問題が発生しているために、CloudFront がドメイン名の解決によって IP アドレスを取得できない場合、Lambda@Edge 関数は呼び出されません。CloudFront は、[HTTP 502 ステータスコード (不正なゲートウェイ)](http-502-bad-gateway.md) をクライアントに返します。詳細については、「[DNS エラー (`NonS3OriginDnsError`)](http-502-bad-gateway.md#http-502-dns-error)」を参照してください。

関数ロジックがオリジンのドメイン名を変更すると、CloudFront は関数の実行完了後に、更新されたドメイン名に対して別の DNS 解決を実行します。

DNS フェイルオーバーの管理の詳細については、「Amazon Route 53 デベロッパーガイド」の「[DNS フェイルオーバーの設定](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/dns-failover-configuring.html)」を参照してください。**

## HTTP ステータスコード
<a name="lambda-at-edge-restrictions-status-codes"></a>

ビューワーレスポンスイベントの Lambda@Edge 関数は、レスポンスがオリジンまたは CloudFront キャッシュからのものであるかどうかにかかわらず、レスポンスの HTTP ステータスコードを変更できません。

## Lambda 関数のバージョン
<a name="lambda-at-edge-restrictions-version"></a>

`$LATEST` やエイリアスではなく、Lambda 関数の番号付きバージョンを使用する必要があります。

## Lambda リージョン
<a name="lambda-at-edge-restrictions-region"></a>

Lambda 関数は、米国東部 (バージニア北部) リージョンにある必要があります。

## Lambda のロール許可
<a name="lambda-at-edge-restrictions-role-permissions"></a>

Lambda 関数に関連付けられている IAM 実行ロールは、サービスプリンシパル `lambda.amazonaws.com` と `edgelambda.amazonaws.com` によるそのロールの引き受けを許可する必要があります。詳細については、「[Lambda@Edge 用の IAM アクセス許可とロールのセットアップ](lambda-edge-permissions.md)」を参照してください。

## Lambda の機能
<a name="lambda-at-edge-restrictions-features"></a>

以下の Lambda 機能は、Lambda@Edge でサポートされていません。
+ **[自動]** (デフォルト) 以外の [Lambda ランタイム管理設定](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-update.html#runtime-management-controls)
+ VPC 内のリソースにアクセスするための Lambda 関数の設定
+ [Lambda 関数のデッドレターキュー](https://docs.aws.amazon.com/lambda/latest/dg/invocation-async.html#dlq)
+ [Lambda 環境変数](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html) (自動的にサポートされる予約環境変数は除く)
+ [レイヤーによる AWS Lambda 依存関係の管理](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html)を使用する Lambda 関数
+ [ の使用AWS X-Ray](https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html)
+ Lambda プロビジョニング済み同時実行
**注記**  
Lambda@Edge 関数には、Lambda 関数と同じ[リージョンの同時実行](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html)機能があります。詳細については、「[Lambda@Edge のクォータ](cloudfront-limits.md#limits-lambda-at-edge)」を参照してください。
+ [コンテナイメージを使用した Lambda 関数の作成](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html)
+ [arm64 アーキテクチャを使用する Lambda 関数](https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html)
+ エフェメラルストレージが 512 MB を超える Lambda 関数
+ [カスタマーマネージドキーを使用した .zip デプロイパッケージの暗号化](https://docs.aws.amazon.com/lambda/latest/dg/encrypt-zip-package.html)

## ランタイムのサポート
<a name="lambda-at-edge-restrictions-runtime"></a>

Lambda@Edge は、最新バージョンの Node.js および Python ランタイムをサポートしています。サポートされているバージョンとその将来の廃止日のリストについては、「*AWS Lambda デベロッパーガイド*」の「[サポートされているランタイム](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtimes-supported)」を参照してください。

**ヒント**  
ベストプラクティスとして、提供されている最新バージョンのランタイムでパフォーマンスを改善し、新しい機能を使用してください。
廃止されたバージョンの Node.js で関数を作成または更新することはできません。これらのバージョンの既存の関数は、CloudFront ディストリビューションにのみ関連付けることができます。これらのバージョンに該当する関数のうち、ディストリビューションに関連付けられているものは、引き続き実行されます。ただし、関数を新しいバージョンの Node.js に移行することをお勧めします。詳細については、「*AWS Lambda デベロッパーガイド*」の「[ランタイムの非推奨化に関するポリシー](https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html)」と、GitHub の [Node.js リリーススケジュール](https://github.com/nodejs/Release#release-schedule)を参照してください。

## CloudFront ヘッダー
<a name="lambda-at-edge-restrictions-cloudfront-headers"></a>

Lambda@Edge 関数は、[CloudFront のリクエストヘッダーを追加する](adding-cloudfront-headers.md) にリストされている任意の CloudFront ヘッダーの読み取り、編集、削除、または追加を行うことができます。

**注意事項**  
これらのヘッダーを CloudFront で追加する場合は、[キャッシュポリシー](controlling-the-cache-key.md)または[オリジンリクエストポリシー](controlling-origin-requests.md)を使用してヘッダーを追加するように CloudFront を設定する必要があります。
CloudFront は、ビューワーリクエストイベントの後にヘッダーを追加します。つまり、ビューワーリクエストの Lambda@Edge 関数ではヘッダーを使用できません。**ヘッダーは、オリジンリクエストとオリジンレスポンスの Lambda@Edge 関数でのみ使用できます。
ビューワーリクエストにこれらの名前を持つヘッダーが含まれており、[キャッシュポリシー](controlling-the-cache-key.md)または[オリジンリクエストポリシー](controlling-origin-requests.md)を使用してこれらのヘッダーを追加するように CloudFront を設定した場合は、CloudFront がビューワーリクエストにあったヘッダー値を上書きします。ビューワー向けの関数はビューワーリクエストからのヘッダー値を認識し、オリジン向けの関数は CloudFront が追加したヘッダー値を認識します。
ビューワーリクエスト関数で `CloudFront-Viewer-Country` ヘッダーを追加すると、検証に失敗し、CloudFront は HTTP ステータスコード 502 (不正なゲートウェイ) をビューワーに返します。

## [本文を含める] オプションを使用する場合のリクエスト本文に対する制限
<a name="lambda-at-edge-restrictions-request-body"></a>

**[本文を含める]** オプションを選択してリクエスト本文を Lambda@Edge 関数に公開する場合は、公開または置換する本文部分に以下の情報およびサイズ制限が適用されます。
+ CloudFront は常に、リクエスト本文を base64 でエンコードしてから、それを Lambda@Edge に公開します。
+ リクエスト本文が大きい場合、CloudFront は、本文を以下のように切り詰めてから Lambda@Edge に公開します。
  + ビューワーリクエストでは、本文が 40 KB で切り捨てられます。
  + オリジンリクエストでは、本文が 1 MB で切り捨てられます。
+ 読み取り専用としてリクエスト本文にアクセスする場合、CloudFront は元の完全なリクエスト本文をオリジンに送信します。
+ Lambda@Edge 関数がリクエスト本文を置き換える場合、関数が返す本文には、以下のサイズ制限が適用されます。
  + Lambda@Edge 関数が本文をプレーンテキストとして返す場合:
    + ビューワーリクエストイベントでは、本文が 40 KB に制限されます。
    + オリジンリクエストイベントでは、本文が 1 MB に制限されます。
  + Lambda@Edge 関数が本文を base64 でエンコードされたテキストとして返す場合:
    + ビューワーリクエストイベントでは、本文が 53.2 KB に制限されます。
    + オリジンリクエストイベントでは、本文が 1.33 MB に制限されます。

**注記**  
Lambda@Edge 関数がこれらの制限を超える本文を返した場合、リクエストは失敗し、HTTP 502 ステータスコード ([Lambda 検証エラー](http-502-bad-gateway.md#http-502-lambda-validation-error)) が返されます。本文がこれらの制限を超えないように Lambda@Edge 関数を更新することをお勧めします。

## レスポンスタイムアウトとキープアライブタイムアウト (カスタムオリジンのみ)
<a name="timeout-for-lambda-edge-functions"></a>

Lambda@Edge 関数を使用してディストリビューションオリジンのレスポンスタイムアウトまたはキープアライブタイムアウトを設定している場合は、オリジンがサポートできる値を指定していることを確認します。詳細については、「[レスポンスとキープアライブのタイムアウトクォータ](DownloadDistValuesOrigin.md#response-keep-alive-timeout-quota)」を参照してください。