Lambda@Edgeで、パスに応じてレスポンスBodyを変える

# はじめに
題名通り、例えば、リクエストのパス配下に`error`が含まれている場合と`success`が含まれている場合で、画面表示を変える方法についてまとめました。

`https://test.com/hoge/error`をリクエスト → エラー画面を表示
`https://test.com/hoge/success`をリクエスト → 成功画面を表示

# 事前準備
・CloudFrontを作成

# 流れ
①Lambda@Edge作成
②コード記入
③Lambda@Edgeデプロイ

# ①Lambda@Edge作成
・リージョンは`バージニア北部`
・1から作成
・関数名:適当に記入
・ランタイム:Node.js
・デフォルトの実行ロールの変更:AWS ポリシーテンプレートから新しいロールを作成を選択
　　→ポリシーテンプレート：基本的な Lambda@Edge のアクセス権限 

・関数の作成をクリック

# ②コード作成

```js:node.js
const success_content = `
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  </head>
  <body>
  成功しました!
  </body>
</html>
`;

const error_content = `
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  </head>
  <body>
  失敗しました
  </body>
</html>
`;

exports.handler = (event, context, callback) => {

    const request = event.Records[0].cf.request;

    const uri = request.uri;
    const uri_success = '\/success\/';
    const uri_error = '\/error\/';

    if(uri.match(uri_success)){
      var display_content = success_content;
    } else if(uri.match(uri_error)){
      var display_content = error_content;
    }

    try {
      const response = {
        status: '200',
        statusDescription: 'OK',
        headers: {
          'content-type': [{
            key: 'Content-Type',
            value: 'text/html'
          }]
        },
        body: display_content
      };
      callback(null, response);
      return;
    } catch (ex) { }

    //requestを変更せずcloudfrontに返す
    callback(null, request);
    return request;
};
```
ここで使用されているuriとbodyの説明は[こちらに書いてあります。](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html)
>`body`は、HTTP リクエストの本文。

>`uri`とは`リクエストされたオブジェクトの相対パス`ことです。
>・新しい uri 値は、スラッシュ (/) で始める必要があります。
>・関数で uri 値を変更すると、ビューワーがリクエストしているオブジェクトが変更されます。
>・関数で uri 値を変更しても、リクエストのキャッシュ動作や送信先オリジンは変わりません。


つまり、`https://test.com/error`場合、uriのパスはerrorになり、successの場合、uriのパスはsuccessになるわけです。
そして、errorの場合は、`error_content`で定義しているコード内容が画面に表示されます。


matchメソッドを用いることで、uriが`/hoge/success/test`の場合でも成功の表示をすることができます。

# ③Lambda@Edgeデプロイ
アクションのLambda@Edgeへデプロイをクリック

・新しい CloudFront トリガーの設定
・ディストリビューション:作成済みのCloudFront
・キャッシュ動作：＊
・CloudFront イベント:ビューワーリクエスト
・Lambda@Edge へのデプロイを確認：チェック

デプロイします。
CloudFrontに遷移し、デプロイが完了したことを確認します。10分程度かかります。

Lambda@Edgeのトリガーをビューワーリクエストに設定すると、CloudFrontがキャッシュを保有しているかに関わらずビューワーからリクエストがある度にLambdaが起動します。
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/7fd84c06-16b0-bc63-8171-d5807831744b.png">

|  |ビューワー  | オリジン  |
|---|---|---|
| リクエスト  |全てのリクエストに対して CloudFront のキャッシュを確認する前に実行  |キャッシュミスの時にオリジンへリクエストを送る前に実行  |
| レスポンス  |全てのリクエストに対してオリジンかキャッシュからレスポンスが応答された後に実行  |キャッシュミスの時にオリジンからレスポンスが応答された後に実行  |




## ログ確認したい場合
CloudWatch Logsのロググループに`/aws/lambda/[Lambda@Edgeの関数名]`で確認できます。
ただし、Lambdaが起動したエッジサーバがあるリージョンにLogが保存されています。東京リージョンになるかと思います。

# 参考文献
[Lambda@Edge イベント構造](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html)
[CloudFrontでLambda@Edgeを使ってHTTPリダイレクトを設定する。](https://qiita.com/kooohei/items/7fcbc3602f7b7026b5a8)
[Lambda@Edge で URLパスを書き換える](https://dev.classmethod.jp/articles/lambdaedge-rewrite-url-path/)