cors - AWS SAM : No 'Access-Control-Allow-Origin' header is present on the requested resource response

标签 cors aws-lambda aws-api-gateway aws-cloudformation aws-sam-cli

我正在努力建立一个静态网站来使用 CORS 调用 API 网关。我已使用 SAM local 运行下面的代码,但尝试从我的静态网站(本地托管)使用 jQuery 调用我的 API 时遇到以下 CORS 错误:

Failed to load http://localhost:3000/notify: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4000' is therefore not allowed access.

我的template.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Api:
    # enable CORS; to make more specific, change the origin wildcard
    # to a particular domain name, e.g. "'www.example.com'"
    Cors: "'*'"

Parameters:
  RecaptchaSecret:
    Type: String

Resources:
  NotifierFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: notifier/build
      Handler: app.lambda_handler
      Runtime: python3.6
      Environment: 
        Variables:
          PARAM1: VALUE
      Events:
        Notify:
          Type: Api 
          Properties:
            Path: /notify
            Method: post

Outputs:
    NotifierApi:
      Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/notify/"
    NotifierFunction:
      Value: !GetAtt NotifierFunction.Arn
    NotifierFunctionIamRole:
      Value: !GetAtt NotifierFunctionRole.Arn

我对 SAM 中的 Globals 部分的理解是,它应该将 Api 字段应用于我的(推断的)API 网关。

我在网上看到了一些使用 API 网关进行 CORS 的示例,其中其他人使用了标准 API 网关模板,还有一些人除了 swagger 文件之外还使用了 SAM,但我一直无法看到成功的示例有人在没有 swagger 文件的情况下使用 SAM 让 CORS 工作(请参阅下面的引用资料)。我觉得我一定错过了一些明显的东西!

我正在使用来自 jQuery 的常规 POST 请求,我可以发布我的前端代码,或者“编译的”CloudForamtion(如果有帮助的话)。

非常感谢任何帮助!

干杯:)

我看过的引用资料:

这是我的函数代码:

import json
import boto3
import requests

def lambda_handler(event, context):
    print "REACHED"
    print event
    ip = requests.get('http://checkip.amazonaws.com/')

    return {
        "statusCode": 200,
        "headers": {"Access-Control-Allow-Origin": "*"},
        "body": json.dumps({
            'message': 'hello world',
            'location': ip.text.replace('\n', ''),
        })
    }

最佳答案

如果您仍然对如何实现这一点感兴趣,可以直接通过 cloudformation 模板完成,如下所示,最好在发布子资源之前定义一个根模拟资源。

  MockMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      RestApiId: STRING
      ResourceId: STRING
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        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: "'POST,OPTIONS'"
              method.response.header.Access-Control-Allow-Origin:* #Note * allows all origins
            SelectionPattern: 2\d{2}
            ResponseTemplates: 
              application/json: Empty
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - 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
          StatusCode: 200

请注意,OPTIONS 是在 POST 方法之前处理预检 CORS 请求的内容。此外,如果您按照下面的方式使用 AWS_PROXY,则需要在 lambda 函数中处理 header CORS 响应。

  POSTmethod: 
    Type: AWS::ApiGateway::Method 
    Properties:  
      HttpMethod: POST 
      RestApiId: STRING
      ResourceId: STRING
      Integration: 
        Type: AWS_PROXY 
        ConnectionType: INTERNET 
        IntegrationHttpMethod: POST 
        Credentials: STRING
        Uri: STRING
        PassthroughBehavior: WHEN_NO_TEMPLATES
        TimeoutInMillis: 10000 #Timeout in 10seconds  
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/json: Empty
          ResponseParameters:
              method.response.header.Access-Control-Allow-Headers: true
              method.response.header.Access-Control-Allow-Origin: true
        - StatusCode: 400
          ResponseModels:
            application/json: Empty

  OPTIONSmethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      RestApiId: STRING
      ResourceId: STRING
      HttpMethod: OPTIONS
      Integration:
        Type: MOCK
        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: "'POST,OPTIONS'"
              method.response.header.Access-Control-Allow-Origin: "'*'"
            SelectionPattern: 2\d{2}
            ResponseTemplates: 
              application/json: Empty
        PassthroughBehavior: WHEN_NO_MATCH
        RequestTemplates:
          application/json: '{"statusCode": 200}'
      MethodResponses:
        - 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
          StatusCode: 200

关于cors - AWS SAM : No 'Access-Control-Allow-Origin' header is present on the requested resource response,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51197080/

相关文章:

amazon-web-services - S3 的私有(private)内容 CORS 问题

javascript - 当使用 aws amplify on react 调用 api 网关时,我该如何获取状态码?

javascript - Spring Boot 和 PreFlight 请求

php - Ajax CORS 替代品

aws-lambda - 对于 LocalStack API Gateway Lambda 集成,我到底应该使用哪个路径进行 cURL?

Python-画中画 : Is it possible to specify architecture?

amazon-web-services - 创建API网关失败

json - Kinesis Firehose 在没有分隔符逗号的情况下将 JSON 对象放入 S3

rest - 使用 CORS 的跨域 REST/Jersey Web 服务

amazon-web-services - Aws Lambda 显示进度