2
1

CloudFront Functions だけでHTTP 503 を返すメンテナンス画面を作る話

Last updated at Posted at 2024-04-03

CloudFront Functionsのみで指定IP以外はメンテナンス画面(html)を表示する方法。検索するとS3と組み合わせる例はたくさん出てくるのですが、この方法は出てこなかったので残しておきます。

S3を組み合わせると困る点

CloudFront -> S3(オリジン)の構成で、S3にメンテ画面用のHTMLを置くとhttps://example.com/mainte.htmlではメンテ画面を出せても、他のURLにアクセスされると404になってしまい、メンテ画面を出せない。

このため、CloudFrontの404ページをmainte.htmlに変更し、ステータスコードも503を返す設定(ディストリビューション→エラーページ→カスタムエラーレスポンス)が必要となる→設定も戻すのも面倒。

CloudFront Functionsでbodyを返却

下記の方法だとビューワーリクエスト(ビヘイビア→関数の関連付け)の関数をメンテ用の関数に変更するだけでメンテナンス画面が出せる。どうやらかつてはbodyを返却することができなかったぽい?のだが、現在は可能。

CloudFront Functions イベント構造
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/functions-event-structure.html

注意点としては、CloudFront Functionsのファイル容量は10KB以内でないと駄目なので、あまりリッチな画面は作れないこと。試してはいないのですが、cssや画像などは200で返っても問題ないので、そのあたりはS3など静的配信可能なものに入れて、それをhtmlで参照すると良さそう。

コード

cloudfront-js-2.0で実行させる

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

    // メンテ画面を出さずに通すIPリスト
    const sourceIP = event.viewer.ip;
    const ALLOWED_IPS = [
        "xx.xx.xx.xx",
        "yy.yy.yy.yy",
    ];

    // メンテナンス用HTML
    const html = `
            <!DOCTYPE html>
            <html>
            <head>
            <title>Site under maintenance</title>
            </head>
            <body>
            <h1>Site under maintenance</h1>
            <p>We are currently performing maintenance on our website. Please check back later.</p>
            </body>
            </html>
            `;
    const base64EncodedBody = Buffer.from(html, "utf8").toString("base64");

    // 指定IP以外はメンテ画面を503で出す
    if (!ALLOWED_IPS.includes(sourceIP)) {
        const response = {
            statusCode: 503,
            statusDescription: "Service Temporarily Unavailable",
            headers: {
                "content-type": {
                    value: "text/html",
                },
                "cache-control": {
                    value: "no-store, no-cache, must-revalidate, max-age=0",
                },
                pragma: {
                    value: "no-cache",
                },
                expires: {
                    value: "0",
                },
            },
            body: {
                data: base64EncodedBody,
                encoding: "base64",
            },
        };

        return response;
    }

    return request;
}

今までmod_rewriteでゴニョゴニョやっていたことを考えると、ずいぶん分かりやすくできることも増えたので、このサービス好き。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1