AWS API Gateway CORS 对 OPTIONS 正常,对 POST 失败
Posted
技术标签:
【中文标题】AWS API Gateway CORS 对 OPTIONS 正常,对 POST 失败【英文标题】:AWS API Gateway CORS ok for OPTIONS, fail for POST 【发布时间】:2017-03-02 04:18:47 【问题描述】:我查看了关于 SO 的其他相关问题,但这似乎有所不同。 其实我的问题和this one很相似,只是我没有400状态问题。
设置:
通过 API 网关的 lambda 函数 授权:无,需要 API KEY:false部署到阶段:测试
1 个资源,1 个集成 lambda 的 POST 方法。
直接调用 POST 端点,例如with curl 总是返回 200(有/没有有效负载、错误有效负载等) - 所以这与引用的问题不同。我已使用“启用 CORS”选项 - 我已尝试在资源和 POST 请求(并随后部署 API)上应用此选项。
在 API GW 中,我可以看到 Access-Control-Allow-Origin
在 POST 方法 - 方法响应区域下的 200 个响应标头中列出。
结果:在 Chrome 中从客户端代码调用端点,OPTIONS 通过但 POST 由于缺少 Access-Control-Allow-Origin
标头而失败。
在 curl 中:OPTIONS 调用
curl -X OPTIONS -H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type" \
-H "Origin: http://example.com" --verbose <endpoint>
回复是:
< HTTP/1.1 200 OK
< Content-Type: application/json
...
< Access-Control-Allow-Headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
< Access-Control-Allow-Methods: POST,OPTIONS
< Access-Control-Allow-Origin: *
...
但使用 POST:
curl -X POST -d '' -H "Content-Type: application/json" \
-H "Origin: http://example.com" --verbose <endpoint>
它返回:
< HTTP/1.1 200 OK
< Content-Type: application/json
...
和响应 json 正文 - 但没有 Access-
anything 标头。
我还能检查什么?
【问题讨论】:
【参考方案1】:问题在于 API 网关使用选中的 "Lambda Proxy Integration"
选项调用了我的 lambda 函数。
我相信在将 API 网关触发器添加到新创建的 lambda 函数时,默认情况下会激活此功能。
在 API Gateway - Resource - Method 视图中,“Integration Response”框显示为灰色,并且似乎无法(即使对于 Enable CORS 功能)在那里添加 Access-Control-Allow-Origin
标头,根据 @ Abhigna_Nagaraja 是必需的。
解决方案:
如果使用“Lambda 代理集成”,请将 'Access-Control-Allow-Origin': '*'
标头添加到您的 lambda 函数中。
更好的是:在同一视图 - 集成请求中,关闭“Lambda 代理集成”并再次启用 CORS(之后部署)。
(然后,在回调中,您必须只返回有效负载 json 而不是 statusCode, headers, body
对象。)
更新:
如果您不确定是在 http 状态代码还是在 json 有效负载中返回请求响应状态信息,请阅读一些有用的信息:
http status vs json status
json status standards
【讨论】:
我相信新的“Lambda 代理集成”已经损坏,因为它只创建了一个新的 ANY 方法。它似乎没有与 CORS 完美集成,甚至与默认的 Lambda 触发器向导也没有完美集成。目前,我只能通过禁用“Lambda 代理集成”并手动创建 GET/POST 方法来解决此问题。 根据我的经验,这部分是有效的。 ANY 方法是一个包罗万象的方法,在 LPI 的情况下,它将所有方法(POST、GET 等)定向到 lambda。但是,如果 lambda 有任何问题,则错误是非常具有误导性的。 “Lambda 代理集成”是一种控制 lambda 函数的状态代码和响应标头的方法。禁用代理集成将始终返回 200 响应,并且只允许您设置响应内容。当使用启用代理集成的 API GW 时,文档提到了在您的 lambda 中设置 CORS 标头。 (docs.aws.amazon.com/apigateway/latest/developerguide/…)【参考方案2】:“启用 CORS”选项是一个方便的工具,可以设置所有集成/方法响应标头映射。如果您单击“启用 CORS”,然后添加了新资源,它将没有所需的设置。您可以再次单击“启用 CORS”,也可以手动将其设置为
将“Access-Control-Allow-Origin”方法响应标头添加到 POST 方法 将“Access-Control-Allow-Origin”集成响应头映射添加到 POST 方法另外,不要忘记在使用 curl 测试更改之前部署 API。
【讨论】:
一切都按照您的建议完成。但是,在使用手动步骤确认时,我注意到一件事:方法响应看起来不错,但无法查看或编辑集成响应。该框显示“代理集成无法配置为转换响应”。我正在使用 Lambda 代理集成。这可能与我看到的问题有关吗? 我能够通过将标头添加到 lambda 回调中的标头部分来获取标头。由于这看起来像是代码和配置的丑陋组合,我怀疑我们不应该在需要 CORS 时使用 Lambda 代理集成? 您知道在 LPI 中将 CORS 标头添加到集成响应中是否已修复?【参考方案3】:如果您愿意使用 serverless-express 在您的 Lambda 中封装一个简单的 Express 应用程序,那么 Express cors
package 可以让这个非常简单且高度可配置为 Lambda 代理。无需在 API Gateway 级别配置 CORS。
index.js
const app = express();
app.use(cors());
// ...your backend implementation
lambda.js
const serverlessExpress = require('@vendia/serverless-express')
const app = require('./app')
exports.handler = serverlessExpress( app )
【讨论】:
以上是关于AWS API Gateway CORS 对 OPTIONS 正常,对 POST 失败的主要内容,如果未能解决你的问题,请参考以下文章
AWS API Gateway + AWS Lambda 中的 CORS
使用 BOTO3 为 AWS Api Gateway 自动化 CORS