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 が増えています。

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

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

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

今回登録したコード(初期値そのまま)はこんな感じ。
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 っぽいリクエストを投げて試しました。

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

問題無さそうなので 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 側で一括で付与できるのは楽になりそう。

AWSTech