AWS API网关支持OPTIONS请求的CORS,但不支持POST请求的CORS。

14

我在 Stack Overflow 上看了其他相关的问题,但这个似乎有所不同。 实际上,我的问题与这个非常相似,只是我没有400状态的问题。

设定如下:

  • 通过API Gateway进行Lambda函数调用
  • 授权:无需API密钥,API KEY Required: false
  • 部署到阶段:test

  • 1个资源,1个POST方法集成Lambda。

  • 直接调用POST端点(例如使用curl)始终返回200(带有效负载或无效负载等),这与参考问题不同。

我已经使用了“启用CORS”选项 - 我尝试将此选项应用于资源和POST请求(然后部署API)。

在API GW中,我可以看到 Access-Control-Allow-Origin 在 POST 方法 - Method Response 区域的 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- 任何头部信息。

我还能检查什么?

3个回答

25
问题在于API网关使用了勾选了“Lambda代理集成”选项来调用我的Lambda函数。
我认为当向新创建的Lambda函数添加API网关触发器时,默认情况下会激活此选项。
在API Gateway - 资源 - 方法视图中,"Integration Response"框是灰色的,看起来似乎无法在其中添加Access-Control-Allow-Origin标头(即使启用了Enable CORS功能),这是@Abhigna_Nagaraja所要求的。
解决方案: 如果使用“Lambda代理集成”,请将'Access-Control-Allow-Origin': '*'标头添加到您的lambda函数中。
更好的方法是:在同一视图-集成请求中,关闭“Lambda代理集成”,然后再次启用CORS(之后部署)。
(然后,在回调中,您需要返回仅有效载荷的json,而不是{statusCode,headers,body}对象。)
更新: 如果您不确定是在http状态代码中返回请求响应状态信息还是在json有效负载中,请阅读以下一些有用的文章: http status vs json status

JSON状态标准


2
我认为新的“Lambda Proxy Integration”有问题,因为它只创建了一个新的ANY方法。它似乎与CORS不完全集成,甚至与默认的Lambda触发器向导也不完美。目前,我只能通过禁用“Lambda Proxy Integration”并手动创建GET / POST方法来解决这个问题。 - alexcasalboni
1
根据我的经验,那部分代码是有效的。ANY方法是一个通用方法,在LPI的情况下,它会将所有的方法(POST、GET等)都传递给lambda函数。然而,如果lambda函数出现任何问题,错误信息可能会非常误导人。 - bebbi
“Lambda Proxy Integration”是一种控制Lambda函数状态码和响应头的方式。禁用代理集成将始终返回200响应,并且只允许您设置响应内容。文档提到,在启用代理集成时,需要在Lambda内设置CORS标头才能使用API GW。(http://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html) - Eelke van den Bos

3
'启用CORS'选项是一种方便的工具,它设置了所有的集成/方法响应头映射。如果您单击了'启用CORS',然后添加了新资源,它将没有必要的设置。您可以再次单击'启用CORS',或者手动设置如下:
  • 在POST方法中添加'Access-Control-Allow-Origin'方法响应头
  • 在POST方法中添加'Access-Control-Allow-Origin'集成响应头映射
另外,在使用curl测试更改之前,请不要忘记部署API。

一切都按照您的建议完成了。然而,当我通过手动步骤确认时,我注意到一个问题:方法响应看起来没问题,但是集成响应无法查看或编辑。提示框显示"代理集成无法配置以转换响应"。我正在使用Lambda代理集成。这可能与我遇到的问题有关吗? - bebbi
1
通过将标头添加到Lambda回调的标题部分,我成功获取了标头。由于那看起来像是代码和配置的丑陋混合,我怀疑在需要CORS时我们不应该使用Lambda代理集成? - bebbi
你知道在LPI中添加CORS头到集成响应是否已经修复了吗? - bebbi

0

如果你愿意使用serverless-express将一个简单的Express应用程序包装在Lambda中,那么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 })

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接