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 资源语法,反之亦然?
请求的资源在 Salesforce 中不存在 [错误]。 Salesforce 出了啥问题?
Angular 7:对预检请求的响应未通过访问控制检查:请求中不存在“Access-Control-Allow-Origin”标头