CloudFront 関数 KeyValueStoresを使ってみた


# はじめに
今回は2023年11月にCloudFront 関数のKeyValueStoresがリリースされたということで早速使ってみましたの今回使ってみました。
今まで以下のような感じでcloudfront関数でURLのリダイレクトを行う場合、関数コードにリダイレクトの変更先の情報を入れていたのですが、関数コードで入力できる容量が少なく多くのリダイレクト先を入れる場合はLambda@Edgeを使用するしかありませんでした。

```
#CloudFront関数のリダイレクトの場合

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

    // Handling based on the request URI using HTTP 301
    if (uri === '/report/') {
        var response = {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { value: 'https://g21hoge.jp/blog/' }
            }
        };
        return response;
    } else if (uri === '/report2/') {
        var response = {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { value: 'https://g21hoge.jp/blog/test' }
            }
        };
        return response;
    } else if (uri === '/report3/') {
        var response = {
            statusCode: 301,
            statusDescription: 'Moved Permanently',
            headers: {
                'location': { value: 'https://g21hoge.jp/blog/test2' }
            }
        };
        return response;
    }

    // Proceed with the original request for other URIs
    return request;
}
```
今回リリースされたKeyValueStoresはJson形式で文字の代替えができるため、イチイチ関数コードにリダイレクト先を書かず尚且つ多くのリダイレクト先を処理できるようになりました。

まずはjsonファイルの準備から、以下のような置換したいkeyに対して特定の内容をvalueに返すjsonファイルを作成します。

```
{
  "data":[
    {
      "key":"/report/",
      "value":"https://g21hoge.jp/blog/"
    },
    {
      "key":"/report2/",
      "value":"https://g21hoge.jp/blog/test1/"
    },
    {
      "key":"/report3/",
      "value":"https://g21hoge.jp/blog/test2/"
    }
  ]
}
```

このファイルをAmazon S3のバケットに置いておき、
次にKeyValueStoresにその内容を読み込ませていきます。

CloudFront関数のKeyValueStoresからCreate KeyValueStoreを押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/c13113db-56fe-6505-d051-3ea22c3e192d.png)

Nameと説明を記入し先ほど作成したJsonファイルがおいてあるS3を参照してCreateを押下します。

作成が成功するとLast modifiedがプロビジョニング状態に一時的になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/5dd2d06f-da4a-50c9-e462-58b437c0fc44.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/4e1c76f6-3629-3e10-8df6-a95eebfc4538.png)

作成が完了すると以下のような形で、KeyとValueが入ります。
これでKeyValueStoresの準備ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/6b186571-7af9-3514-f3ce-b20f762654b0.png)

次はCloudFront関数で作成したKeyValueStoresを紐づけて使用できるようにします。

CloudFront関数を作成後、Associate existing KeyValueStoreを選択して、作成したKeyValueStoreを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/2de43368-970a-985e-0df0-6f2bd064ed5d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624667/f96f8c68-02af-d92b-5e5a-e26878f65a39.png)

次に関数コードでKeyValueStoreからリクエストされた内容を返すコードを作成します。
以下は自分が今回作ったものになります。

```
import cf from 'cloudfront';

const kvsId = 'fbfefbc6-d46c-4c5c-8975-602f7e5d3017';
const kvsHandle = cf.kvs(kvsId);

async function handler(event) {
    const request = event.request;
    const uri = request.uri;

    // KVSからリダイレクト先のURLを取得
    let redirectUrl;
    try {
        redirectUrl = await kvsHandle.get(uri);
        if (redirectUrl) {
            return {
                statusCode: 301,
                statusDescription: 'Moved Permanently',
                headers: { 'location': { value: redirectUrl } }
            };
        }
    } catch (err) {
        console.log(`KVS lookup failed for ${uri}: ${err}`);
    }

    // リダイレクト先が見つからない場合、404エラーを返す
    return {
        statusCode: 404,
        statusDescription: 'Not Found'
    };
}
```

const kvsId = は作成したKeyValueStoresのIDを入れてください。
あとはこのまま変更を保存して、対象のディストリビューションのビヘイビアにつけてあげればKeyValueStoresを参照して文字を置換しリダイレクトを行ってくれるようになります。
データストアには最大5MBのデータを保存でき、キーの最大サイズは512バイト、値の最大サイズは1KBです。
利用費は100万回の読み取りあたり 今は$0.03です。なので大量の文字を使用してCloudFront関数を利用しながら書き換えを行いたいというときにこのKeyValueStoresを使えば実現できるようになりました。