【问题标题】:enabling CORS for AWS API gateway with the AWS CDK使用 AWS CDK 为 AWS API 网关启用 CORS
【发布时间】:2019-03-16 01:43:53
【问题描述】:

我正在尝试使用 AWS CDK 构建应用程序,如果我要使用 AWS 控制台手动构建应用程序,我通常会在 API 网关中启用 CORS。

即使我可以将 swagger 导出到 API Gateway 之外,并且找到了许多为 OPTIONS 方法生成 Mock 端点的选项,但我不知道如何使用 CDK 执行此操作。目前我正在尝试:

const apigw             = require('@aws-cdk/aws-apigateway');

在哪里:

var api                 = new apigw.RestApi(this, 'testApi');

并定义 OPTIONS 方法,如:

const testResource   = api.root.addResource('testresource');

var mock = new apigw.MockIntegration({
                    type: "Mock",
                    methodResponses: [
                            {
                                    statusCode: "200",
                                    responseParameters : {
                                            "Access-Control-Allow-Headers" : "string",
                                            "Access-Control-Allow-Methods" : "string",
                                            "Access-Control-Allow-Origin" : "string"
                                    }
                            }
                    ],
                    integrationResponses: [
                            {
                                    statusCode: "200",
                                    responseParameters: {
                                            "Access-Control-Allow-Headers" :  "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
                                            "Access-Control-Allow-Origin" : "'*'",
                                            "Access-Control-Allow-Methods" : "'GET,POST,OPTIONS'"
                                    }
                            }
                    ],
                    requestTemplates: {
                            "application/json": "{\"statusCode\": 200}"
                    }
            });

            testResource.addMethod('OPTIONS', mock);

但这并没有部署。我在运行“cdk deploy”时从 cloudformation stack deploy 得到的错误消息是:

Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: Access-Control-Allow-Origin] (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException;

想法?

【问题讨论】:

    标签: amazon-cloudformation aws-api-gateway aws-cdk


    【解决方案1】:

    recent change 使启用 CORS 变得更简单:

    const restApi = new apigw.RestApi(this, `api`, {
      defaultCorsPreflightOptions: {
        allowOrigins: apigw.Cors.ALL_ORIGINS
      }
    });
    

    【讨论】:

    • 如果您启用了binaryMediaTypes,这将不起作用。
    【解决方案2】:

    我自己没有对此进行测试,但根据 this answer,您在定义 MOCK 集成时似乎需要使用一组稍微不同的键:

    const api = new apigw.RestApi(this, 'api');
    
    const method = api.root.addMethod('OPTIONS', new apigw.MockIntegration({
      integrationResponses: [
        {
          statusCode: "200",
          responseParameters: {
            "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,POST,OPTIONS'",
            "method.response.header.Access-Control-Allow-Origin": "'*'"
          },
          responseTemplates: {
            "application/json": ""
          }
        }
      ],
      passthroughBehavior: apigw.PassthroughBehavior.Never,
      requestTemplates: {
        "application/json": "{\"statusCode\": 200}"
      },
    }));
    
    // since "methodResponses" is not supported by apigw.Method (https://github.com/awslabs/aws-cdk/issues/905)
    // we will need to use an escape hatch to override the property
    
    const methodResource = method.findChild('Resource') as apigw.cloudformation.MethodResource;
    methodResource.propertyOverrides.methodResponses = [
      {
        statusCode: '200',
        responseModels: {
          'application/json': 'Empty'
        },
        responseParameters: {
          'method.response.header.Access-Control-Allow-Headers': true,
          'method.response.header.Access-Control-Allow-Methods': true,
          'method.response.header.Access-Control-Allow-Origin': true
        }
      }
    ]
    

    如果能够使用更多 friendly API 启用 CORS,将会很有用。

    【讨论】:

    • 我同意一个更友好的 API 会非常有帮助,但这至少能让我前进并且它确实有效。谢谢!
    【解决方案3】:

    编辑:随着 CDK 的更新,不再需要使用逃生舱口。请查看其他答案,因为它们更干净。

    原答案:

    This version, originally created by Heitor Vital on github uses only native constructs.

    export function addCorsOptions(apiResource: apigateway.IResource) {
        apiResource.addMethod('OPTIONS', new apigateway.MockIntegration({
            integrationResponses: [{
            statusCode: '200',
            responseParameters: {
                'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
                'method.response.header.Access-Control-Allow-Origin': "'*'",
                'method.response.header.Access-Control-Allow-Credentials': "'false'",
                'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
            },
            }],
            passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
            requestTemplates: {
            "application/json": "{\"statusCode\": 200}"
            },
        }), {
            methodResponses: [{
            statusCode: '200',
            responseParameters: {
                'method.response.header.Access-Control-Allow-Headers': true,
                'method.response.header.Access-Control-Allow-Methods': true,
                'method.response.header.Access-Control-Allow-Credentials': true,
                'method.response.header.Access-Control-Allow-Origin': true,
            },  
            }]
        })
    }
    

    我还使用他的版本作为指导,将相同的代码移植到 python。

    def add_cors_options(api_resource):
        """Add response to OPTIONS to enable CORS on an API resource."""
        mock = apigateway.MockIntegration(
            integration_responses=[{
                'statusCode': '200',
                'responseParameters': {
                    'method.response.header.Access-Control-Allow-Headers':
                        "'Content-Type,\
                          X-Amz-Date,\
                          Authorization,\
                          X-Api-Key,\
                          X-Amz-Security-Token,X-Amz-User-Agent'",
                    'method.response.header.Access-Control-Allow-Origin': "'*'",
                    'method.response.header.Access-Control-Allow-Credentials':
                        "'false'",
                    'method.response.header.Access-Control-Allow-Methods':
                        "'OPTIONS,\
                          GET,\
                          PUT,\
                          POST,\
                          DELETE'",
                }
            }],
            passthrough_behavior=apigateway.PassthroughBehavior.NEVER,
            request_templates={
                "application/json": "{\"statusCode\": 200}"
            }
        )
        method_response = apigateway.MethodResponse(
            status_code='200',
            response_parameters={
                'method.response.header.Access-Control-Allow-Headers': True,
                'method.response.header.Access-Control-Allow-Methods': True,
                'method.response.header.Access-Control-Allow-Credentials': True,
                'method.response.header.Access-Control-Allow-Origin': True
            }
        )
        api_resource.add_method(
            'OPTIONS',
            integration=mock,
            method_responses=[method_response]
        )
    

    【讨论】:

      【解决方案4】:

      背景

      我在尝试在 Terraform 中实现 aws_api_gateway_integration_response 时遇到了这个答案,并且意外地遇到了解决方案。

      问题

      我收到此错误消息:

      Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: POST,GET,OPTIONS]

      aws_api_gateway_integration_response 资源中,我将response_parameter 键设为:

      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-Origin" = "*"
          "method.response.header.Access-Control-Allow-Methods" = "POST,GET,OPTIONS"
          # "method.response.header.Access-Control-Allow-Credentials" = "false"
        }
      

      我认为一切都很好,因为我认为双引号就是 Terraform 所需要的。然而,事实并非如此。

      解决方案

      我必须在双引号内的值周围添加一个单引号。像这样:

      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-Origin" = "'*'"
          "method.response.header.Access-Control-Allow-Methods" = "'POST,GET,OPTIONS'"
          # "method.response.header.Access-Control-Allow-Credentials" = "false"
        }
      

      【讨论】:

        猜你喜欢
        • 2021-09-15
        • 2021-10-14
        • 2021-08-26
        • 2019-03-08
        • 2019-05-10
        • 2020-05-28
        • 2021-09-04
        • 2021-03-08
        • 2020-02-20
        相关资源
        最近更新 更多