AWS SAM:请求的资源响应中不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】AWS SAM:请求的资源响应中不存在“Access-Control-Allow-Origin”标头【英文标题】:AWS SAM: No 'Access-Control-Allow-Origin' header is present on the requested resource response 【发布时间】:2018-12-14 06:38:36 【问题描述】:

我正在努力让一个静态网站使用 CORS 调用 API 网关。我已经使用本地 SAM 运行了下面的代码,但是尝试从我的静态网站(本地托管)使用 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,但我一直无法看到成功的示例有人让 CORS 在没有 swagger 文件的情况下使用 SAM 工作(参见下面的参考资料)。我觉得我一定遗漏了一些明显的东西!

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

非常感谢任何帮助!

干杯:)

我看过的参考资料:

https://github.com/awslabs/serverless-application-model/tree/master/examples/apps/api-gateway-multiple-origin-cors

https://github.com/awslabs/serverless-application-model/issues/373

https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#data-types

这是我的功能代码:

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', ''),
        )
    

【问题讨论】:

我不太了解这种创建模板的方式,能否给我看一下函数代码,特别是它返回的响应。基本上我总是从函数中返回正确的标题。 嘿!我添加了功能代码。基本上只是添加了 CORS 的 hello-world。 嗯,这很奇怪,请问 APIG 中的集成类型是什么?所以基本上进入控制台,点击api,点击方法,是Lambda Proxy吗? 嘿!抱歉这么久才回复你。集成类型(在“集成请求”下)实际上是“Lambda 代理”。 此 sam 模板不会将“Access-Control-Allow-Origin”添加到您的 OPTIONS 资源中。添加它并确保您的 lambda 正确返回 Access-Control-Allow-Headers" 标头。 【参考方案1】:

如果您仍然对如何实现这一点感兴趣,可以按照下面的方式直接通过 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\d2
            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 函数中处理标头 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\d2
            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

【讨论】:

以上是关于AWS SAM:请求的资源响应中不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

对预检请求的响应未通过访问控制检查:请求的资源中不存在“Access-control-Allow-Origin”标头

我能否在 SAM 模板中使用 AWS Cloud Formation 资源语法,反之亦然?

从 http 网页请求本地资源时响应为 401 错误

请求的资源在 Salesforce 中不存在 [错误]。 Salesforce 出了啥问题?

aws sam 发布/部署流程

Angular 7:对预检请求的响应未通过访问控制检查:请求中不存在“Access-Control-Allow-Origin”标头