AWS API 方法失败并出现 504 错误;使用 Cognito 和 CORS
Posted
技术标签:
【中文标题】AWS API 方法失败并出现 504 错误;使用 Cognito 和 CORS【英文标题】:AWS API Method fails with 504 Error; Using Cognito and CORS 【发布时间】:2018-09-13 09:16:38 【问题描述】:总结:
我将进入下面的杂草,但基本上我的最终目标是从 AWS Lambda 函数中检索一个值并将其返回到我页面的客户端。该页面使用 AWS Cognito 对用户进行身份验证,一旦通过身份验证,它就会发布到 API Gateway 端点,以从我的 Lambda 函数检索数据(Lambda 查询 DynamoDB)。这是我正在努力解决的部分,因为我收到了 504(超时)错误。
我知道我的 Lambda 正确返回值,并且我的 API 在理论上已正确实施,或者至少在 API Gateway 管理控制台的测试部分可以正常工作。
详情:
我花了很多时间试图找出我的错误所在,我相信这与 Cognito 身份验证或 CORS 有关。如果我从我的 API 网关方法中删除授权要求并且不发送授权令牌,那么我会从帖子中得到预期的响应。这让我相信我的问题的根源可能是在 Post 方法上错误地实现了 Cognito 授权。
我正在使用 CORS,因为该站点托管在 EC2 上,但使用 AWS API Gateway 进行 RESTful 路由。
另外,我使用 Cognito javascript SDK 对用户进行身份验证,然后将 authToken 传递到我的 ajax 中的自定义标头中。
这是我的 ajax:
$.ajax(
method: 'POST',
url: _config.api.invokeUrl + '/getusersites',
dataType: "json",
crossDomain: true,
cors: true,
xhrFields:
withCredentials: true
,
headers:
Authorization: token
,
data: JSON.stringify(user),
success: completeRequest,
error: ajaxError
);
现在,除非我有误解,否则当我查看 Chrome 的 DevTools 的“网络”选项卡中的标题时,似乎帖子在预检时失败了。因为当我查看那个 URL 的 General 部分时,它说:
请求方法:OPTIONS
状态码:504
(有关完整标题,请参阅下面的更新)
身体是:
"message": "端点请求超时"
所以这会让我相信 CORS 的 Option 请求在 Post 甚至被调用之前就已经超时了。
我也收到控制台错误:
加载失败(此处是我的 API 端点):对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin '(My origin domain)' 因此不允许访问。响应的 HTTP 状态代码为 504。
所以在我看来,CORS 预检未能在 API 超时之前做出响应。
我没有在我的 API 资源上的 Options 方法的方法执行中启用授权,但我确实为 Post 方法启用了它。正如我之前所说,如果我禁用它,那么一切都会按预期工作,只是没有 Cognito 授权检查。
那么我在这里做错了什么?这是CORS问题吗?授权问题?两者都有?
我的尝试:
我尝试将 CORS 标头添加到我的 Post 方法的集成响应中。但是,我相信这并没有什么不同,因为它们只会返回 200(成功)代码,而我得到的是 504 代码。
我认为我的 Lambda 函数或我的 Cognito 用户池的授权方可能存在权限问题。所以我进入了 IAM 并给了他们他们可能想要的所有权限。这并没有改变结果。
我根据我的 ajax 可能设置不正确的理论工作,所以我尝试了几种不同的方法来实现帖子的参数,但是唯一有效的方法是如果我禁用授权并且不发送带有身份验证令牌的自定义标头。
我确保我的 API 资源已启用 CORS 并已重新部署。要是这么简单就好了。
我已经用谷歌搜索了足够多的谷歌服务器,但我无法问这个问题。
最后的想法:
如果您花时间阅读我的小说,我将不胜感激。如果有人尝试做类似的事情或对方向有任何想法,我可以继续处理这个问题。我仍在学习如何处理所有这些 AWS 实施,所以我确定我只是在某个地方犯了一些愚蠢的错误。
提前感谢您的回复。
>>>更新:
根据请求,以下是 OPTION 尝试的完整标头。由于 OPTION 尝试出现 504 错误,因此没有 POST。
一般:
请求 URL:https://(API 端点).amazonaws.com/prod/getusersites
请求方法:OPTIONS
状态码:504
远程地址:52.84.11.37:443
推荐人政策:no-referrer-when-downgrade
响应标头:
内容长度:41
内容类型:应用程序/json
日期:格林威治标准时间 2018 年 4 月 4 日星期三 16:16:14
状态:504
通过:1.1 0a9f4502819b08c3a7919c963887be2b.cloudfront.net (CloudFront)
x-amz-apigw-id: E0wHvE3doAMFgrA=
x-amz-cf-id:pVgd6gNNtw-cYxKe4s9jdEnfU2rBle8cd9MyP34aduYi0_ds4YBRCA==
x-amzn-requestid: 6e014d82-3823-11e8-bc41-3f13ca287d3c
x-cache:来自云端的错误
请求头:
:authority: (API 端点)
:方法:选项
:路径:/prod/getusersites
:方案:https
接受:/
接受编码:gzip、deflate、br
接受语言:en-US,en;q=0.9
访问控制请求头:授权
访问控制请求方法:POST
缓存控制:无缓存
来源:https://(来源域)
编译指示:无缓存
用户代理:Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit/537.36(Khtml,如 Gecko)Chrome/65.0.3325.181 Safari/537.36
【问题讨论】:
好的,首先是愚蠢的问题 - 您是否确保您的 Web 服务器完全允许 OPTIONS 请求?对 CORS 预检的 504 响应在我看来只是您的 Web 服务器(Apache 或其他)设置为仅允许 GET、POST 和可能的 HEAD ...如果您可以提供全套请求/响应标头,这将很有用(对于 OPTIONS 和 POST 请求。 我确定 Web 服务器设置正确,因为当我删除身份验证要求时,会返回预期值。我会用完整的标题更新我的问题。 【参考方案1】:花了很长时间,但我终于弄清楚出了什么问题。
问题是当我通过 AWS API Gateway 控制台实现 CORS 时,AWS 如何设置 OPTIONS 集成请求。
默认情况下,它将集成请求设置为 HTTP,使用 API 调用 URL 作为端点。出于某种原因,这导致 OPTIONS 预检超时并以 504 响应。仍然不知道为什么,可能与身份验证有关。
解决方案:
在我的 OPTIONS 方法的集成请求部分,我将集成类型从 HTTP 更改为 MOCK。
然后,保存之后,我必须转到我的 OPTIONS 方法的集成响应部分,展开 200 HTTP 状态代码,展开标头映射并重新输入我的标头的值。标题仍然存在,但值已被删除。我的最终响应标题如下所示:
Access-Control-Allow-Headers 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'
Access-Control-Allow-Origin 'https://MyDomain.com'
Access-Control-Allow-Credentials 'true'
Access-Control-Allow-Methods 'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'
设置这些之后,我重新部署了 API,它运行良好!现在我要去喝一瓶香槟了。 :)
【讨论】:
以上是关于AWS API 方法失败并出现 504 错误;使用 Cognito 和 CORS的主要内容,如果未能解决你的问题,请参考以下文章
调用某些外部 api url 时,aws EC2 中的 504 超时
在 Vercel 上部署的 Nextjs 中的 api 请求出现 504/502 错误
API 失败,错误域=NSURLErrorDomain 代码=-1003