虽然已通过API网关设置了CORS并且设置了Access-Control-Allow-Origin
标头,但在尝试从Chrome中的AJAX调用API时仍会收到以下错误:
XMLHttpRequest无法加载http://XXXXX.execute-api.us-west-2.amazonaws.com/beta/YYYYY。 No' Access-Control-Allow-Origin'标头出现在请求的资源上。起源' null'因此不允许访问。响应的HTTP状态代码为403。
我尝试通过Postman获取网址,并显示上述标题已成功通过:
来自OPTIONS的回应:
如何在不恢复为JSON-P的情况下从浏览器调用我的API?
答案 0 :(得分:69)
我遇到了同样的问题。我用了10个小时才发现。
https://serverless.com/framework/docs/providers/aws/events/apigateway/
// handler.js
'use strict';
module.exports.hello = function(event, context, callback) {
const response = {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : "*", // Required for CORS support to work
"Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
},
body: JSON.stringify({ "message": "Hello World!" })
};
callback(null, response);
};
答案 1 :(得分:47)
如果还有其他人遇到这种情况 - 我能够在应用程序中找到根本原因。
如果您使用自定义授权程序运行API-Gateway,API-Gateway将在实际命中服务器之前发送401或403。默认情况下 - 从自定义授权程序返回4xx时,未为CORS配置API网关。
此外 - 如果您恰好从通过API网关的请求中获取了0
或1
的状态代码,则可能是您的问题。
要修复 - 在API网关配置中 - 转到"网关响应",展开"默认4XX"并在那里添加一个CORS配置头。即。
Access-Control-Allow-Origin: '*'
确保重新部署您的网关 - 瞧!
答案 2 :(得分:9)
1)我需要和@riseres一样做以及其他一些更改。这是我的回复标题:
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Headers':'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
'Access-Control-Allow-Credentials' : true,
'Content-Type': 'application/json'
}
2)
根据此文件:
http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html
在API网关配置上使用代理进行lambda函数时,post或get方法没有添加标题,只有选项可以。您必须在响应中手动执行(服务器或lambda响应)。
3)
除此之外,我还需要在API网关帖子方法中禁用“API Key Required”选项。
答案 3 :(得分:9)
让我的示例正常工作:我只是在标题中插入'Access-Control-Allow-Origin':'*',:{} 在生成的nodejs Lambda函数中。我对Lambda生成的API层进行了 no 更改。
这是我的NodeJS:
'use strict';
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
exports.handler = ( event, context, callback ) => {
const done = ( err, res ) => callback( null, {
statusCode: err ? '400' : '200',
body: err ? err.message : JSON.stringify(res),
headers:{ 'Access-Control-Allow-Origin' : '*' },
});
switch( event.httpMethod ) {
...
}
};
这是我的AJAX电话
$.ajax({
url: 'https://x.execute-api.x-x-x.amazonaws.com/prod/fnXx?TableName=x',
type: 'GET',
beforeSend: function(){ $( '#loader' ).show();},
success: function( res ) { alert( JSON.stringify(res) ); },
error:function(e){ alert('Lambda returned error\n\n' + e.responseText); },
complete:function(){ $('#loader').hide(); }
});
答案 4 :(得分:7)
我刚刚在lambda函数响应中添加了标头,它的工作原理就像一个魅力
var arr = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a4", value: 1},{name: "a2", value: 1}];
var arr2 = [{name: "a1", value: 1},{name: "a3", value: 1},{name: "a14", value: 1},{name: "a12", value: 1}];
var arr3 = [{name: 1, value: 1},{name: 11, value: 1},{name: 14, value: 1},{name: 12, value: 1}];
var sort = function (prop, arr) {
prop = prop.split('.');
var len = prop.length;
arr.sort(function (a, b) {
var i = 0;
while( i < len ) {
a = a[prop[i]];
b = b[prop[i]];
i++;
}
let [key1,digit1] = (""+a).split(/(?<=[a-z])(?=\d)/)
let [key2,digit2] = (""+b).split(/(?<=[a-z])(?=\d)/)
return (key1 - key2) || (+digit1 - +digit2)
});
return arr;
};
arr = sort('name', arr);
arr2 = sort('name', arr2);
arr3 = sort('name', arr3)
console.log(arr); // it's correct
console.log(arr2); // it's not correct
console.log(arr3);
答案 5 :(得分:3)
对我来说,最终有效的答案是Alex R的答案中James Shapiro的评论(第二高的评价)。首先,我试图通过在S3中托管一个静态网页来使用lambda处理与我们联系的页面并发送电子邮件来解决这个API网关问题。只需检查[]默认4XX,即可修复错误消息。
答案 6 :(得分:2)
当我意识到lambda授权者失败并且由于某种未知的原因被转化为CORS错误后,我开始工作了。对我的授权人的一个简单修复(以及我应该首先添加的一些授权人测试)就可以了。对我来说,需要API网关操作“启用CORS”。这样就在API中添加了我需要的所有标头和其他设置。
答案 7 :(得分:2)
为POST
和OPTIONS
启用CORS之后部署代码对我来说很有效。
答案 8 :(得分:1)
如果您尝试了所有与该问题无关的尝试,那么您将以我所做的一切而告终。事实证明,亚马逊现有的CORS设置说明工作正常……只需确保您记住要重新部署! CORS编辑向导即使带有所有漂亮的绿色小标记,也不会实时更新您的API。也许很明显,但是它让我难过了半天。
答案 9 :(得分:1)
对我来说,因为我使用的是非常标准的 React fetch 调用,所以这可以使用上面的一些 AWS 控制台和 Lambda 修复来修复,但是我的 Lambda 返回了正确的标头(我也使用了代理模式),我需要将我的应用程序打包成一个 SAM 模板,所以我不能花时间在控制台上点击。
我注意到所有 CORS 内容都运行良好,直到我将 Cognito Auth 放到我的应用程序中。我只是在使用越来越多的配置进行 SAM 包/SAM 部署时速度非常慢,直到它坏了,只要我将 Auth 添加到我的 API 网关,它就坏了。我花了一整天的时间点击像这样的精彩讨论,寻找一个简单的解决方法,但最终不得不实际阅读 CORS 正在做什么。我会为您节省阅读时间,并为您提供另一个简单的解决方案(至少对我而言)。
以下是最终有效的 API 网关模板示例 (YAML):
Resources:
MySearchApi:
Type: AWS::Serverless::Api
Properties:
StageName: 'Dev'
Cors:
AllowMethods: "'OPTIONS, GET'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowOrigin: "'*'"
Auth:
DefaultAuthorizer: MyCognitoSearchAuth
Authorizers:
MyCognitoSearchAuth:
UserPoolArn: "<my hardcoded user pool ARN>"
AuthType: "COGNITO_USER_POOLS"
AddDefaultAuthorizerToCorsPreflight: False
注意底部的 AddDefaultAuthorizerToCorsPreflight。根据我的阅读,如果您的模板中没有它,则默认为 True。并且,当为 True 时,它会阻止正常的 OPTIONS 行为,以宣布资源在允许的来源方面支持什么。一旦我明确添加它并将其设置为 False,我的所有问题都解决了。
这意味着如果您遇到此问题并想要更完整地诊断它,您应该访问 API Gateway 中的资源并检查您的 OPTIONS 方法是否包含某种形式的身份验证。您的 GET 或 POST 需要 Auth,但如果您的 OPTIONS 启用了 Auth,那么您可能会发现自己处于这种情况。如果您在 AWS 控制台周围单击,请尝试从 OPTIONS 中删除,重新部署,然后进行测试。如果您使用的是 SAM CLI,请尝试我上面的修复。
答案 10 :(得分:1)
对于Google员工:
这是原因:
GET
/ POST
不会发送预检OPTIONS
配置为使用模拟响应发送Allow-Origin
标头Allow-Origin
标头OPTIONS
之后的请求自行发送CORS标头答案 11 :(得分:1)
更改功能或代码后,请遵循以下两个步骤。
首先启用CORS ,然后部署API 。
答案 12 :(得分:0)
对于在 API Gateway 中使用 Cognito 授权器的用户,实际上无需设置自定义网关响应。 API 网关会阻止预检,因为它们在默认的 AWS 逻辑中是“未经授权的”。
幸运的是,有一个内置参数可以解决这个问题。只需将 AddDefaultAuthorizerToCorsPreflight: False
添加到您的 API Authorizer 中,API Gateway 将禁用飞行前请求的身份验证。这是 documentation 和示例设置:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors:
AllowHeaders: "'*'"
AllowMethods: "'*'"
AllowOrigin: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
AddDefaultAuthorizerToCorsPreflight: False
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
答案 13 :(得分:0)
确保您调用的是正确的路径。
无论出于何种原因,命中不存在的路径都可能导致 CORS 相关错误。可能是因为 404
在其响应中不包含 CORS 标头。
感谢@jackko 对最初问题的评论。这是我的问题。听起来很傻,但可能发生在任何人身上。
答案 14 :(得分:0)
答案 15 :(得分:0)
除了其他注释外,还需要注意的是从基础集成返回的状态,以及是否为该状态返回了Access-Control-Allow-Origin标头。
执行“启用CORS”操作只会设置200个状态。如果端点上还有其他对象,例如4xx和5xx,则需要自己添加标头。
答案 16 :(得分:0)
此问题的另一个根本原因可能是HTTP / 1.1和HTTP / 2之间的差异。
症状:某些用户(并非所有人)报告在使用我们的软件时收到CORS错误。
问题:Access-Control-Allow-Origin
标头有时 丢失。
上下文:我们有一个Lambda,专用于处理OPTIONS
请求并使用相应的CORS标头进行回复,例如与白名单{{1}匹配的Access-Control-Allow-Origin
}。
解决方案:对于HTTP / 2调用,API网关似乎将所有标头都转换为小写,但是对于HTTP / 1.1则保持大写。这导致对Origin
的访问失败。
检查您是否也遇到此问题:
假设您的API位于event.headers.origin
,而您的前端位于https://api.example.com
。使用CURL,使用HTTP / 2发出请求:
https://www.example.com
响应输出应包含标题:
curl -v -X OPTIONS -H 'Origin: https://www.example.com' https://api.example.com
使用HTTP / 1.1(或使用小写的< Access-Control-Allow-Origin: https://www.example.com
标头)重复同一步骤:
Origin
如果缺少curl -v -X OPTIONS --http1.1 -H 'Origin: https://www.example.com' https://api.example.com
标头,则在读取Access-Control-Allow-Origin
标头时可能要检查是否区分大小写。
答案 17 :(得分:0)
就我而言,由于我使用AWS_IAM作为Authorization方法,因此我需要授予IAM角色访问终端的权限。
答案 18 :(得分:0)
我正在运行aws-serverless-express
,在我的情况下需要编辑simple-proxy-api.yaml
。
在将CORS配置为https://example.com
之前,我只是交换了网站的名称,并通过npm run setup
重新部署,并更新了我现有的lambda / stack。
#...
/:
#...
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
/{proxy+}:
method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
#...
答案 19 :(得分:-1)
就我而言,我只是在错误地编写提取请求网址。在serverless.yml
上,将cors
设置为true
:
register-downloadable-client:
handler: fetch-downloadable-client-data/register.register
events:
- http:
path: register-downloadable-client
method: post
integration: lambda
cors: true
stage: ${self:custom.stage}
,然后在lambda处理程序上发送标头,但是如果在前端使提取请求出错,则不会在响应上获取该标头,并且会得到此错误。因此,请在前面仔细检查您的请求URL。
答案 20 :(得分:-2)
在Python中,您可以按照以下代码进行操作:
{ "statusCode" : 200,
'headers':
{'Content-Type': 'application/json',
'Access-Control-Allow-Origin': "*"
},
"body": json.dumps(
{
"temperature" : tempArray,
"time": timeArray
})
}
答案 21 :(得分:-2)