Lambda@Edgeはオリジンサーバーの返すレスポンスボディーを書き換えられない

Lambda@Edge(以下 L@E) は以下の箇所でリクエスト・レスポンス内容を書き換えられます。

Conceptual graphic that shows CloudFront trigger events for Lambda functions that integrate with CloudFront.

(図は https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-cloudfront-trigger-events.html から)

この図を眺めていると、L@E の Origin Response の箇所に Lambda 関数を用意すれば、オリジンサーバーを改修せずに HTML を部分的に書き換えられるというアイデアが浮かぶ方がいるかも知れません。

残念ながら、 現在の L@E はレスポンスボディーにアクセスできないため、書き換えられません。

When you’re working with the HTTP response, note that Lambda@Edge does not expose the HTML body that is returned by the origin server to the origin-response trigger

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-updating-http-responses.html

本ブログでは、実際にこの挙動を確認してみます。

なお

  • レスポンスヘッダーの追加
  • レスポンスボディー全体を Lambda で新規に生成

といったことは可能です。

検証コード

次の Lambda 関数を用意し、オリジンサーバーのレスポンスをキャッシュする前に呼び出します。

'use strict';

exports.handler = (event, context, callback) => {
    const response = event.Records[0].cf.response;
    response.headers['foo'] = [{key: 'foo', value: 'bar'}]; // レスポンスヘッダーの書き換え
    response.body = response.body + '/* appended body */';  // レスポンスボディーの書き換え
    callback(null, response);
};
  • レスポンスヘッダーに、"foo" がキーの新規ヘッダーを追加
  • レスポンスボディーをオリジンのレスポンスボディー(response.body)に文字列を追記したものに変更

しているだけです。

この L@E をデプロイ後、 CloudFront に GET リクエストし、レスポンスを確認します。

$ curl -D - https://CF_HOST.cloudfront.net/index.html
HTTP/2 200
content-type: text/html
content-length: 28
accept-ranges: bytes
date: Tue, 08 May 2018 17:28:31 GMT
etag: "e8e3b45cbaea21cd7ce7c323a71e98b5"
foo: bar
last-modified: Tue, 08 May 2018 12:05:04 GMT
server: AmazonS3
x-cache: Miss from cloudfront
via: 1.1 CF_HOST.cloudfront.net (CloudFront)
x-amz-cf-id: ReUfBmHOPXeDsZR9gXboPD5CMhXfDyzAn5pw0O5itIPrefqCjn43Xg==

undefined/* appended body */

レスポンスヘッダーには L@E で追加した foo: bar を確認できます。

一方で、レスポンスボディーは undefined/* appended body */ となっています。

L@E で expose されていない response.bodyundefined となり、文字列連結により、そのまま文字列 undefinedとして、/* appended body */ と連結されています。

残念ながら、オリジンの返す response.body を DOM 操作や正規表現でゴニョゴニョすることはできません。

最後に

本ブログが Lambda@Edge ではオリジンの返すレスポンスボディーをいじれないことに少しでも早く気づくきっかけになれば幸いです。

参考