CloudFront Functions を使ってリダイレクトサーバを作る

2021-05-04AWSTech

CloudFront 上で JavaScript を実行できる CloudFront Functions なる機能が出てきました。
この機能を用いて、CloudFront 単体でリダイレクトサーバを立ててみます。

ヘッダ編集など軽めの処理が想定されていて、画像処理やレスポンス生成など重めの処理は、既存の Lambda@Edge を引き続き使うことが推奨されています。価格は Lambda@Edge の 1/6 でお安い。

利用用途と活用例

AWS 公式ブログ を見ると以下の例が挙げられています。

  • キャッシュキーの操作や正規化
  • URL 書き換えやリダイレクト
  • HTTP ヘッダ操作
  • アクセスコントロール

User-Agent を見てデバイス種別でキャッシュキーをまとめたり、条件を満たさない場合にリダイレクトかけたり、HSTS ヘッダを CloudFront 側で付与したり、JWT の検証をしたりなどなど。

最大実行時間が 1ms、メモリ上限が 2MB なので本当に軽い処理で使うのが無難そう。

(5/6追記) 実行時間が 1ms を超えた場合は 503 が返ります。

CloudFront Functions タイムアウトエラー

CloudFront Functions を試してみる

CloudFront コンソールを開くと左メニューに Functions が増えています。

CloudFront Functions を作成する

適当に名前をつけると、Lambda のようなエディタが出てきました。

CloudFront Functions のエディタ

とりあえず何も変えずに保存して Publish します。

CloudFront Functions を公開する

Distribution、Event type、Behavior を選択して紐付ければ終わり。

CloudFront Functions の紐付け

今回登録したコード(初期値そのまま)はこんな感じ。
200 のステータスコードで cloudfront-functions というヘッダを返しています。

function handler(event) {
    var response = {
        statusCode: 200,
        statusDescription: 'OK',
        headers: {
            'cloudfront-functions': { value: 'generated-by-CloudFront-Functions' }
        }
    };
    return response;
}

実際に叩いてみたところ、上記通りのレスポンスが返ってきました。
真ん中あたりに cloudfront-functions がいます。

% curl -i https://hoge.yuu26.com
HTTP/2 200
server: CloudFront
date: Tue, 04 May 2021 07:32:01 GMT
content-length: 0
cloudfront-functions: generated-by-CloudFront-Functions
x-cache: FunctionGeneratedResponse from cloudfront
via: 1.1 5216b5aef38f6d8e7d7ca4ab8c47ead0.cloudfront.net (CloudFront)

CloudFront をリダイレクトサーバとして使う

先ほどのコードを以下のように書き換えて、再度 Publish してみます。
CloudFront Functions の書き方は 公式ドキュメント を参考に。

function handler(event) {
    var response = {
        statusCode: 301,
        statusDescription: 'Moved Permanently',
        headers: {
            'location': { value: 'https://blog.yuu26.com/' }
        }
    };
    return response;
}

応答が 301 に切り替わりました。割とすぐ反映されるようです。
FunctionGeneratedResponse from cloudfront というメッセージも見えますね。

% curl -i https://hoge.yuu26.com
HTTP/2 301
server: CloudFront
date: Tue, 04 May 2021 07:38:57 GMT
content-length: 0
location: https://blog.yuu26.com/
x-cache: FunctionGeneratedResponse from cloudfront
via: 1.1 1906941751220f747982bec9cf3c2480.cloudfront.net (CloudFront)

次は User-Agent を見てリダイレクト先を振り分けてみましょう。
iPhone からのアクセスであれば Amazon に飛ばしてみます。(雑)

function handler(event) {
    var redirectUrl = 'https://blog.yuu26.com/';
    var userAgent = event.request.headers['user-agent'];

    if (userAgent != null && userAgent.value.match(/iPhone/)) {
        redirectUrl = 'https://www.amazon.co.jp/';
    }

    var response = {
        statusCode: 302,
        statusDescription: 'Found',
        headers: {
            'location': { value: redirectUrl }
        }
    };
    return response;
}

テスト用ツールも用意されていて、任意のリクエスト内容をシミュレートできます。
今回は IP アドレス 1.2.3.4 から iPhone っぽいリクエストを投げて試しました。

CloudFront Functions のテスト機能

生成されたレスポンスと Function の実行ログを確認できます。

CloudFront Functions のテスト結果

問題無さそうなので Publish してから確認。

% curl -i https://hoge.yuu26.com
HTTP/2 302
server: CloudFront
date: Tue, 04 May 2021 08:01:16 GMT
content-length: 0
location: https://blog.yuu26.com/
x-cache: FunctionGeneratedResponse from cloudfront
via: 1.1 0932afdcbb622a4425fd671f0d67863a.cloudfront.net (CloudFront)

% curl --user-agent 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X)' -i https://hoge.yuu26.com
HTTP/2 302
server: CloudFront
date: Tue, 04 May 2021 08:01:19 GMT
content-length: 0
location: https://www.amazon.co.jp/
x-cache: FunctionGeneratedResponse from cloudfront
via: 1.1 c29e436c21072b427d47688aaf874625.cloudfront.net (CloudFront)

https://hoge.yuu26.com から試せます。iPhone で踏むと Amazon に飛ばされるはず。

まとめ

  • CloudFront Functions というのが出た
  • CDN のエッジで JavaScript を実行できる
  • ヘッダ操作など軽めの処理におすすめ

個人的に便利そうだなーと思ったのは HSTS のヘッダ追加用途。
CloudFront 側で一括で付与できるのは楽になりそう。