背景
- API を API Gateway + Lambda で作成している
- 1つの Cloudfront ディストリビューションで API など動的なレスポンスと画像などの静的なレスポンスを供給する構成としている
- API Gateway のエンドポイントタイプは「リージョン」を選択している
※以下の設定内容は本番環境で十分に検証されたものでは無いことに注意。
CloudFront の設定
いろいろハマったりしたが、以下のような設定に落ち着いた。
- API Gateway に対応する Origin を作成
- Origin ID は "API Gateway / {API名}" みたいにわかり易いものにする
- Minimum Origin SSL Protocol は "TLSv1.2" を選択
- Origin Protocol Policy は "HTTPS Only" を選択
- API の path (
api/*
など) に対して API Gateway に転送するための Behavior 設定を追加- Viewer Protocol Policy は HTTPS Only
- Cache Based on Selected Request Headers で Whitelist を選択
- API で必要なヘッダを明示的に Whitelist に追加する
- Object Caching は Customize を選択
- Minimum TTL, Maximum TTL, Default TTL を 0 にする
- Forward Cookies は必要に応じて設定
- 自分のケースでは
_session_id
を Whitelist に追加してオリジン側(Lambda関数)に渡すように設定した
- 自分のケースでは
- Query String Forwarding and Caching は Forward all, cache based on all を選択
ハマった点
CloudFront の Origin 設定で Origin Protocol Policy が HTTP Only になっていた
- API Gateway は HTTPS のみサポートなので HTTPS Only とするのが正しい
Cache Based on Selected Request Headers の設定が All になっていた
-
All
とした場合Host
ヘッダもそのまま(Cloudfrontに割当てられたドメイン名そのまま)オリジン(API Gateway)に転送される -
そうした場合、API Gateway のSSL証明書とホスト名の不一致で Forbidden が返される
- curlで再現してみる
$ curl https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/test -v -H 'Host:hoge.example.com' * Connection state changed (MAX_CONCURRENT_STREAMS updated)! < HTTP/2 403 < date: Mon, 20 May 2019 06:53:31 GMT < content-type: application/json < content-length: 23 < x-amzn-requestid: fad71491-7acb-11e9-a176-0bf199e4dfca < x-amzn-errortype: ForbiddenException < x-amz-apigw-id: Z-FE0G7htjMFaGw= < * Connection #0 to host xxxxxx.execute-api.ap-northeast-1.amazonaws.com left intact {"message":"Forbidden"}
-
上記の理由により、 API が必要なヘッダを明示的に指定する必要あり
- たとえば、自分のケースだと API Gateway 経由で Lambda 関数を実行するには以下のヘッダが必要だった
Accept
Accept-Encoding
Accept-Language
- Cache Based on Selected Request Headers で、 Whitelist を選択し、上記のヘッダを Whitelist に追加
- たとえば、自分のケースだと API Gateway 経由で Lambda 関数を実行するには以下のヘッダが必要だった
じゃあキャッシュを禁止するには?
- もともと、CloudFrontでのAPIのキャッシュを無効化するつもりで「All」の設定を行っていた
- 「All」の指定ができないとしたら、どうやってキャッシュを無効化するか?
- とりあえず、Behaviour の 各TTL設定(Minimum, Maximum, Default)を
0
とした