Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

CloudFront + API Gatewayの構成でCloudFront-Is-Mobile-Viewerなどのヘッダーを参照する時の注意点

はじめに

CloudFrontからオリジンへのリクエスト時に特定のHTTPヘッダーを含めるには、オリジンリクエストポリシーの設定が必要です。

docs.aws.amazon.com

CloudFrontを使用すると一部HTTPヘッダーが書き換えられ、特にUser-AgentヘッダーAmazon CloudFrontになってしまい、オリジンサーバーでUser-Agentを利用してデバイスの判定ができなくなります。

ただし、オリジンリクエストポリシーでCloudFront-Is-Mobile-Viewerといったヘッダーをオリジンリクエストに追加することで、オリジンサーバーでCloudFront-Is-Mobile-Viewerヘッダーの値を使ってデバイスの判定ができるようになります。

@nuxtjs/deviceといったライブラリでは、このヘッダーに応じてデバイスの判定をすることができ、CloudFrontを導入してUser-AgentがAmazon CloudFrontになってしまっても、そのままレスポンシブ対応をすることができます。

github.com

そんな便利なオリジンリクエストポリシーのヘッダー追加機能ですが、CloudFront + API Gatewayの構成の構築をしていて、CloudFront-Is-Mobile-Viewerといったヘッダーの値が意図したものにならないことがありました。

ヘッダーの値が意図したものにならなかった時の状況

  • ビヘイビアでオリジンをLambda関数にルーティングするAPI Gatewayに設定する。
  • 上記ビヘイビアのオリジンリクエストポリシーでCloudFront-Is-Mobile-Viewerを追加する。
  • API GatewayからルーティングされるLambda関数はSSRでHTMLを配信している。(モバイルかデスクトップかで表示を分けたい)
  • モバイルでアクセスしても、Lambda関数でAPI Gatewayからのリクエストヘッダーを見ると、CloudFront-Is-Mobile-Viewerfalseになっている。
  • また、オリジンリクエストポリシーで設定した覚えのないヘッダーがなぜか追加されている。
'cloudfront-forwarded-proto': 'https',
'cloudfront-is-desktop-viewer': 'true',
'cloudfront-is-mobile-viewer': 'false',
'cloudfront-is-smarttv-viewer': 'false',
'cloudfront-is-tablet-viewer': 'false',
'cloudfront-viewer-country': 'JP',

構成図

問題の原因

API GatewayのEndpoint Typeをエッジ最適化(Edge)にしていたため。

Endpoint Typeをリージョン(Regional)にすることで、モバイルからアクセスしたときにCloudFront-Is-Mobile-Viewerの値はtrueになり、設定した覚えのないヘッダーが送信されることもなくなりました。

API Gatewayのドキュメントによると、エッジ最適化 API エンドポイントの場合、こちらが設定したCloudFront ディストリビューションとは別にCloudFront ディストリビューションを経由することになるため、そちらのヘッダーが適用されることになってしまったのではないかと考えられます。

リージョン API エンドポイントではCloudFront ディストリビューションを経由せず、リージョン固有の API Gateway API を直接ターゲットとするため、こちらが設定したCloudFront ディストリビューションのヘッダーが適用されて、意図したヘッダーをLambda関数で取得することができたと考えられます。

CloudFrontを導入する意図がクライアントへの接続時間の改善であれば、CloudFront + API Gateway(リージョンAPIエンドポイント)の構成ではなく、API Gateway(エッジ最適化 API エンドポイント)で十分かもしれません。

CloudFrontからAPI Gatewayへのオリジンリクエストでヘッダーを追加する場合、エッジ最適化 API エンドポイントで設定していると、ヘッダーの値が意図しない値になったり、意図しないヘッダーが追加されている可能性があるのでご注意ください。