AWS API 网关 CORS

AWS API Gateway CORS

我正在使用 Terraform 部署我的 AWS 基础设施。部署 REST API 资源时,出现错误(如图所示)。 我启用了 CORS,但它一直告诉我 CORS 有问题。但是,当我在 AWS 控制台中使用相同的参数创建相同的资源时,我没有任何错误并且一切顺利。就在通过 Terraform 创建它时,我遇到了这种错误。 这是我的 Terraform 代码:​​

resource "aws_api_gateway_rest_api" "api" {
  name = "api"
  binary_media_types = [
    "image/jpeg",
  ]
}

# ----------------------------------------------------------------------
# CREATE API RESOURCE
# ----------------------------------------------------------------------
resource "aws_api_gateway_resource" "resource" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  parent_id   = aws_api_gateway_rest_api.api.root_resource_id
  path_part   = "upload"
}

# ----------------------------------------------------------------------
# CREATE API RESOURCE METHOD
# ----------------------------------------------------------------------
resource "aws_api_gateway_method" "method" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  resource_id   = aws_api_gateway_resource.resource.id
  http_method   = "POST"
  authorization = "NONE"
}

# ----------------------------------------------------------------------
# ATTACH LAMBDA functions TO METHOD (INTEGRATION)
# ----------------------------------------------------------------------
resource "aws_api_gateway_integration" "integration" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.method.http_method

  integration_http_method = "POST"
  type                    = "AWS"
  uri                     = aws_lambda_function.addImageToS3.invoke_arn
  passthrough_behavior    = "WHEN_NO_MATCH"
  request_templates = {                 
    "image/jpeg" = "${file("mapping_template.template")}"
  }  
}


# ----------------------------------------------------------------------
# ADD PERMISSION TO API SO THAT IT CAN INVOKE THE FUNCTION
# ----------------------------------------------------------------------
resource "aws_lambda_permission" "api-permission" {
statement_id = "AllowExecutionFromApiGateway"
action        = "lambda:InvokeFunction"
function_name = "${aws_lambda_function.addImageToS3.function_name}"
principal = "apigateway.amazonaws.com"
}

# ----------------------------------------------------------------------
# DEPLOY API
# ----------------------------------------------------------------------
resource "aws_api_gateway_deployment" "deployment" {
  depends_on = [
    aws_api_gateway_integration.integration
  ]
  rest_api_id = aws_api_gateway_rest_api.api.id
  stage_name  = "fnp"
}

# ----------------------------------------------------------------------
# BODY OF LAMBDA
# ----------------------------------------------------------------------
data "archive_file" "addImageToS3" {
  type        = "zip"
  source_file = "./functions/addImageToS3.py"
  output_path = "./functions/addImageToS3.zip"
}

# ----------------------------------------------------------------------
# CREATE FUNCTION TO DESCRIBE PROCESSOR: RUNNING,STARTING OR STOPPED
# ----------------------------------------------------------------------
resource "aws_lambda_function" "addImageToS3" {
  filename      = "./functions/addImageToS3.zip"
  function_name = "addImageToS3"
  role          = aws_iam_role.api_assumRoleLambda.arn
  handler       = "addImageToS3.lambda_handler"
  runtime = "python3.8"
  environment {
    variables = {
      region     = var.region
      access_key = var.access_key
      secret_key = var.secret_key
    }
  }
}

# ----------------------------------------------------------------------
# Lambda Execution Role
# ----------------------------------------------------------------------
resource "aws_iam_role" "api_assumRoleLambda" {
  name               = "api_assumRoleLambda"
  assume_role_policy = file("./policies/assumRoleLambda.json")
}

# ----------------------------------------------------------------------
# POLICY TO DECRYPTE ENVIRONMENT VARIABLES 
# ----------------------------------------------------------------------
resource "aws_iam_role_policy" "kms_policy" {
  name   = "kmsDecrypte"
  role   = aws_iam_role.api_assumRoleLambda.id
  policy = file("./policies/kms_policy.json")
  depends_on = [
    aws_iam_role.api_assumRoleLambda, 
  ]
}

output "url" {
  value = aws_api_gateway_deployment.deployment.invoke_url
}


resource "aws_api_gateway_method_response" "cors-post" {
  depends_on = [aws_api_gateway_method.method]
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.method.http_method
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Headers" = true
  }
  response_models = {
    "application/json" = "Empty"
  }
}

resource "aws_api_gateway_integration_response" "cors-post" {
  depends_on = [aws_api_gateway_integration.cors, aws_api_gateway_method_response.cors-post]
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.method.http_method
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'", # replace with hostname of frontend (CloudFront)
    "method.response.header.Access-Control-Allow-Headers" = "'Content-Type'",
    "method.response.header.Access-Control-Allow-Methods" = "'GET, POST'" # remove or add HTTP methods as needed
  }
}


# ----------------------------------------------------------------------
# CORS
# ----------------------------------------------------------------------

resource "aws_api_gateway_method" "cors" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method   = "OPTIONS"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "cors" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.cors.http_method
  type = "MOCK"
}

resource "aws_api_gateway_method_response" "cors" {
  depends_on = [aws_api_gateway_method.cors]
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.cors.http_method
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true,
    "method.response.header.Access-Control-Allow-Methods" = true,
    "method.response.header.Access-Control-Allow-Headers" = true
  }
  response_models = {
    "application/json" = "Empty"
  }
}

resource "aws_api_gateway_integration_response" "cors" {
  depends_on = [aws_api_gateway_integration.cors, aws_api_gateway_method_response.cors]
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.resource.id
  http_method = aws_api_gateway_method.cors.http_method
  status_code = 200
  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'", 
    "method.response.header.Access-Control-Allow-Headers" = "'Content-Type'",
    "method.response.header.Access-Control-Allow-Methods" = "'GET, POST'" # remove or add HTTP methods as needed
  }
}

resource "aws_api_gateway_gateway_response" "response_4xx" {
   rest_api_id = aws_api_gateway_rest_api.api.id
  response_type = "DEFAULT_4XX"

  response_templates = {
    "application/json" = "{'message':$context.error.messageString}"
  }

  response_parameters = {
    "gatewayresponse.header.Access-Control-Allow-Origin" = "'*'" # replace with hostname of frontend (CloudFront)
  }
}

resource "aws_api_gateway_gateway_response" "response_5xx" {
   rest_api_id = aws_api_gateway_rest_api.api.id
  response_type = "DEFAULT_5XX"

  response_templates = {
    "application/json" = "{'message':$context.error.messageString}"
  }

  response_parameters = {
    "gatewayresponse.header.Access-Control-Allow-Origin" = "'*'"
  }
}

在映射模板中:

{
  "content":"$input.body",
  "key":"$input.params('name')"
}

感谢您的回复

检查生成的 json 并注意到在使用 Terraform 部署后未添加一些 http 方法