LoginSignup
15
14

More than 3 years have passed since last update.

CloudFrontにおけるWebPの選択的レスポンス

Last updated at Posted at 2018-10-19

WebPファイルがある場合、対応ブラウザにはそれを返すWebサーバーの設定方法について書いてきました。

S3に画像ファイルを配置するケースも増えていますが、S3自体には上記の代替となるようなURL書き換えの仕組みがありません。

そこでCloudFrontにリクエストやレスポンスを変換するロジックを実装できる、Lambda@Edgeを使う方法を試してみました。

Lambda@Edge用JavaScriptコード

このようなJavaScriptコードを書きました。

Acceptヘッダは簡単に取得できます。WebP画像(image.png.webp)の有無は実際にオリジンに対してHEADリクエストを送信して確認します。

S3に限らず汎用的なWebサーバをオリジンにできます。

実際に設定するには、CloudFrontの対象BehaviorLambda Function AssociationsOrigin Requestとして対してこのLambda関数を割り当てます。Include Bodyは不要です。

Whitelist HeadersAcceptを追加することも必要です。

const BASE_URL = 'https://s3.amazonaws.com/webp-lambda-edge-test';
const TIMEOUT = 3 * 1000;

const https = require('https'),
    url = require('url');

exports.handler = async (event, context) => {
    const request = event.Records[0].cf.request;

    // JpegまたはPNGファイルへのリクエストのみ対応
    if (request.uri.match(/\.(jpe?g|png)$/)) {
        // Acceptヘッダがimage/webpを含むか
        let webpAcceptable = false;
        try {
            if (request.headers.accept[0].value.match(/image\/webp/i))
                webpAcceptable = true;
        } catch (ex) {}

        if (webpAcceptable) {
            // WebP対応ブラウザの場合はWebP版ファイルの有無をHEADメソッドで確認
            await new Promise((resolve, reject) => {
                const webpUri = request.uri + '.webp';
                const req = url.parse(BASE_URL + webpUri);
                req.method = 'HEAD';
                req.timeout = TIMEOUT;
                https.request(req, res => {
                    // ステータスコード2XXであればWebPが存在するのでリクエストURIを変更
                    if (res.statusCode >= 200 && res.statusCode < 300)
                        request.uri = webpUri;
                    resolve();
               }).on('error', reject).end();
            });
        }
    }

    return request;
};

Lambda@Edgeは、通常のLambda関数と異なる点がいくつかあるようです。

Lambda 関数の要件と制限

設定について詳しい手順もまた今度、書いてみたいと思います。

15
14
3

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
15
14