🦀

API GatewayでCORSを有効にするためにやったこと

2021/01/23に公開

はじめに

AWS API Gatewayをつかっていて、CORSまわりの設定が地味に時間を削ってきたので、後陣のためにメモっておきたい

CORS関連のヘッダがつかない..

API GatewayのLambda Proxy Integration(ラムダプロキシ統合、以降LPI)を使っている場合、Enable CORSをするだけでは、いい感じのCORS関連ヘッダーをつけてくれない(その他の統合方法だとやってくれるのだが..)

どんなレスポンスヘッダの設定になってんのかなと、Integration Response(統合レスポンス)を見にいくも、グレーアウトされている。LPI以外だと、ここでヘッダつけてくれるんだと思う[1]

どうすればいいのか?

LPIを使ってる状況でCORSを許可したい時は以下の三つをすればよいようだ(たぶん)

  1. Lambda側でヘッダを返す
  2. Preflightを使えるようにOPTIONSAuthorizationNONEにしておく[2]
  3. エラーレスポンスがCORSで弾かれないように、エラーレスポンスにもヘッダをつける

1. Lambda側でヘッダを返す

コード内で、ヘッダをつけるようにする

lambda_handler.rb
def lambda_handler(event:, context:) 
:
:
  { 
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Headers": "Content-Type",
      "Access-Control-Allow-Origin": '*',
      "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
    },
    body: JSON.generate(list_project(table))
  }
:
:
end

2. OPTIONSAuthorizationNONEにしておく

API Gateway>API>OPTIONS

3. エラーレスポンスにもヘッダをつける

  1. だけだと、ラムダまで届かない(API Gatewayでエラーになる等)場合のレスポンスはヘッダがつかなくて、ブラウザでCORSでブロックされる。そうなると、何が起こってるのかわからず、一見CORSのエラーに見えるけど認証エラーだったとか、切り分けがややこしいのでやっておくとよい

API Gateway>API>Gateway Response>Default 4xxDefault 5xxあたり

公式ドキュメントはどうなっているか

しっかり読めばわかるんだろうけど、「なんでそうなってんの?」がわかりにくい

  • CORSそのものや、シンプルリクエストかどうか、どういうものがCORS対象かについては、ここに記載がある
  • 具体的な設定方法はここにあるが、以下の記載などは怪しいと思う。

重要
上記の手順をプロキシ統合の ANY メソッドに適用すると、適切な CORS ヘッダーは設定されません。代わりに、バックエンドは Access-Control-Allow-Origin などの適切な CORS ヘッダーを返す必要があります。

実際やってみたけど、ANYじゃなくてもCORSのヘッダーはつかないんだな...

Lambda または HTTP プロキシ統合への CORS のサポートを有効にする
Lambda プロキシ統合、または HTTP プロキシ統合の場合、API Gateway で必要な OPTIONS レスポンスヘッダーを引き続き設定できます。ただし、プロキシ統合は統合レスポンスを返さないため、バックエンドは Access-Control-Allow-Origin および Access-Control-Allow-Headers を返します。

OPTIONSだけは、いい感じでやってくれているようなんですが、なんでOPTIONSだけ?

あ、あと、API Gatewayの変更はDeployしないと反映されないので、そこもうっかり忘れてハマりがち。また、Deployの反映は数分かかるので落ち着いて待つこと

シリーズ

脚注
  1. Method Responseの方でなんとかならないかとも思うが、詳しくは調べていない ↩︎

  2. これでいいのかな?もっといい方法があれば誰か教えて欲しい ↩︎

Discussion