モヒカンメモ

髪色が定期的に変わることに定評のある(比較的)若者Webエンジニアの備忘録

Lambda@Edgeではオリジンのデータを部分的に書き換えて返すことはできない

ちょっと何を言っているか分からないと思うけど、自分も分かりたくなかった!

ざっくりまとめ

  • AWS CloudFrontにはいわゆるエッジコンピューティングを提供する Lambda@Edge がある
  • Lambda@Edgeではオリジンから返ってきたbodyの一部を書き換えて返すことは(パパッとは)できない

bodyどこーーー

Lambda@Edgeとは

aws.amazon.com

AWSが提供するCDNサービスCloudFrontに付随する、エッジコンピューティングサービス。配信先のユーザに近いサーバでLambdaを実行して結果を返したら速くコンテンツ提供できるよねーというやつ

ESI (Edge Side Includes) やりたいとか、基本静的コンテンツしか返さないんだけどごく一部で動的にしたいんだよねーでもpathは変えたくないしサーバも用意したくないんだよねーみたいなときに使えそうなやつ

やりたかったこと

CloudFront + S3な構成において、特定のリクエストパラメータが指定された場合にコンテンツの一部を書き換えて配信したい

例えば、S3におっきなjson置いといて ?limit=10&page=1 みたいなクエリパラメータがついていたらjsonの一部だけを返す、みたいな感じ

GET /posts

Response:
{
    "posts": [
        // たくさんのPost
    ]
}
GET /posts?limit=10&page=1

Response:
{
    "posts": [
        // id 1 - 10までのPost
    ]
}

Lambda 関数をトリガーできる CloudFront イベント を呼んで、下記の図でいう Origin Response をトリガーにLambda@Edgeを動かせばやりたいことできそうだと思うじゃん?

https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/images/cloudfront-events-that-trigger-lambda-functions.png

Lambda@Edge 関数の例 とか見てもRequestとResponseそれぞれいじっているようなコードがポコポコ書かれてるし、テンプレートエンジンのレンダリングとかに使えるんじゃねみたいな記事もどこかで見かけたし、絶対行けそうだと思うじゃん????

オリジンから返ってきたbodyはLambda@Edgeで読めない

雑にPoCコード書いてたら、衝撃の事実に気づく

イベントの構造 レスポンスイベント

response event

おわかり頂けただろうか?

response headerはしっかり渡ってくるけど、 response bodyは渡ってこない!!! ママ〜!!!!!!!!

いやいやそんなばかなー、と思ってググったら「それ仕様やで」っていうクラメソの記事もヒット

dev.classmethod.jp

やっぱりそういうことらしいですわ。ぐぬぬー

じゃあどうすんの?

任意のbodyを返すことは出来るので、response bodyが渡って来ないならしょうがないから自分でS3 getするしかない。でも、トリガーが Origin Response のままだとCFがS3 getしたあと自分でもS3 getする感じになって無駄なので、トリガーを Origin Request に変えて、

  • 所定のパラメータがついていなかったらオリジンにそのまま問い合わせさせる
  • 所定のパラメータがついていたら自分でS3 getしてフィルタリング、オリジンに問い合わせさせずにresponseを返す

って感じにするのがスマートかなあ。

リクエストトリガーでの HTTP レスポンスの生成

もしもっといい方法があったらマジで教えて下さい!

っていうか何でこんな仕様になってるの?教えてエロい人