はじめに
Amazon API GatewayとS3の静的Webサイトホスティングを組み合わせると、サーバレスで何でもできるようになるのだけど、当然のことながらオリジンが変わってしまうので、CORSの設定が必要。
マネコンからは一発でCORSの設定を入れることができるものの、IaCと組み合わせてると、マネコンからの変更は色々と不都合があるので、ここはTerraform一撃でCORSの設定を入れられるようにしてしまおう。
CORSって何?という人はクラメソ先生に教えてもらおう!
簡単なリクエスト編(GETメソッド)
GETについては、レスポンスのheadersでCORSを許容することを示せば良い。
具体的には、Access-Control-Allow-Headers
、Access-Control-Allow-Origin
、Access-Control-Allow-Methods
を返す。
以下はPython+API Gatewayの統合レスポンスで返す場合の例。
return {
'isBase64Encoded': False,
'statusCode': status_code,
'headers': {
"Access-Control-Allow-Headers" : "*",
"Access-Control-Allow-Origin": "[許容するオリジン]",
"Access-Control-Allow-Methods": "GET"
},
'body': json.dumps(body)
}
プリフライトリクエスト編(OPTIONメソッド)
プリフライトリクエストについては、Lambdaで実装しても良いが、いちいちLambdaなんて作っていられないので、API Gatewayの統合でMockを使うことにする。
まずは、API GatewayのRESTAPIと、リソースを作成し、
resource "aws_api_gateway_rest_api" "test" {
name = local.api_gateway_name
description = "テスト用API Gateway"
}
resource "aws_api_gateway_resource" "test" {
rest_api_id = aws_api_gateway_rest_api.test.id
parent_id = aws_api_gateway_rest_api.test.root_resource_id
path_part = "test"
}
OPTIONメソッドを定義する。
resource "aws_api_gateway_method" "test_options" {
rest_api_id = aws_api_gateway_rest_api.test.id
resource_id = aws_api_gateway_resource.test.id
http_method = "OPTIONS"
authorization = "NONE"
}
testのOPTIONメソッドに対する統合レスポンスを作りつつ、メソッドレスポンスでCORSのヘッダを透過するよう設定し、
resource "aws_api_gateway_method_response" "test_options_200" {
rest_api_id = aws_api_gateway_rest_api.test.id
resource_id = aws_api_gateway_resource.test.id
http_method = aws_api_gateway_method.test_options.http_method
status_code = "200"
response_models = {
"application/json" = "Empty"
}
response_parameters = {
"method.response.header.Access-Control-Allow-Headers" = true,
"method.response.header.Access-Control-Allow-Methods" = true,
"method.response.header.Access-Control-Allow-Origin" = true
}
}
resource "aws_api_gateway_integration_response" "test_options" {
rest_api_id = aws_api_gateway_rest_api.test.id
resource_id = aws_api_gateway_resource.test.id
http_method = aws_api_gateway_method.test_options.http_method
status_code = aws_api_gateway_method_response.test_options_200.status_code
response_parameters = {
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
"method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'",
"method.response.header.Access-Control-Allow-Origin" = "'[許容するオリジン]'"
}
}
testパスのOPTIONSメソッドに対して200応答をするモックを作成する。
resource "aws_api_gateway_integration" "test_options_mock" {
rest_api_id = aws_api_gateway_rest_api.test.id
resource_id = aws_api_gateway_resource.test.id
http_method = aws_api_gateway_method.test_options.http_method
type = "MOCK"
request_templates = {
"application/json" = <<EOF
{
"statusCode": 200
}
EOF
}
}
これでOPTIONリクエストに良い感じにCORS許容のレスポンスをしてくれるモックが作れた!
あとは好きなようにPOSTなりPUTのメソッドでCORSな更新系リクエストを作れるぞ!