繁体   English   中英

AWS API Gateway OPTIONS 请求返回 500 错误

[英]AWS API Gateway OPTIONS requests returns 500 error

我对 API 网关和 Lambda 很陌生。 我正在尝试将基于 Node.js Express 的 API 部署到 lambda。 我正在使用 awslabs 中的aws-serverless-express 示例 因此,我的大部分 AWS 配置都是自动为我创建的。

看起来我的 API 通过 API 网关正常工作。 我的帖子和获取方法工作正常。 但是,我需要支持 CORS。 我的应用程序应该对 OPTIONS 请求返回正确的 CORS 响应,但它不能在 AWS 上运行。

最终,无论我做什么,我都会收到对选项请求的 500 响应。 我一直无法弄清楚如何获取有关这 500 个错误的任何信息。 我不确定是什么原因造成的。

这是 500 响应的主体{"message": "Internal server error"}

这些是响应标头:

内容长度:36

内容类型:应用程序/json

日期:2017 年 7 月 9 日,星期日 17:56:24 GMT

状态:500

通过:1.1 9af17e5a616bfc9ac07fc7e415ade9e6.cloudfront.net (CloudFront)

x-amz-cf-id:1_AZmkLqf1rjkog2MRtvcBAe54aIZdPWmNApBTwG48Af-v_g9WHkZw==

x-amzn-requestid:ec216a62-64cf-11e7-ad2b-4f1e96508dba

x-cache:来自云端的错误

我很确定我的 OPTIONS 请求甚至没有到达 Lambda 上的应用程序。

我已经尝试使用 API 网关(以及在我的应用程序中)配置 CORS。 我正在尝试将其配置为允许所有来源。

如果有任何我可以查看或做的事情来调试这个问题?

编辑:

为了调试此问题,我尝试为 API 网关启用 CloudWatch 日志记录。

API 网关的 CloudWatch 配置

这样做之后,我在 CloudWatch 中看到了这两个类似网关的日志:

在此处输入图像描述

我一直在使用 prod 所以我点击那个链接看到这个:

在此处输入图像描述

我假设这是一长串日志条目。 我不确定在这种情况下“流”是什么意思。 这些条目有数百个。 因此,我选择了具有最新时间戳的那个并单击它。 现在我看到这个:

在此处输入图像描述

似乎我所有的网关日志都是这样的。 即:显然是空的。

那么,我是否正确设置了日志记录? 我找对地方了吗?

我有与@scopchanov 类似的问题。

在我的 AWS Lambda + API Gateway + Serverless Framework 1.42.3 + Express.js 项目中有效的是:

  1. 我必须启用 CORS/从 Express 发送标头:

    // AWS API Gateway CORS(选项)支持有问题? app.use(cors({credentials: true})); app.options("*", cors());

  2. 不要在 API 网关中启用 CORS,即不要在serverless.yml中这样做:

    • http: method: ANY path: '{proxy+}' # 会导致 {"message": "Internal server error"} # cors: true

没有cors: true ,所有请求都可以正常工作。

使用cors: trueOPTIONS请求将以{"message": "Internal server error"}响应(不管 Lambda 函数做什么,这似乎是由 API 网关直接发送的,或者是有问题的 MOCK 集成)。

对于那些使用aws-serverless-express仍然面临 OPTIONS 500 错误的人,解决方案是将contentHandling: CONVERT_TO_TEXT添加到Swagger 模板中的 OPTIONS 方法

这是包含//{proxy+}路径的 swagger 模板文件

---
swagger: 2.0
info:
  title: AwsServerlessExpressApi
basePath: /prod
schemes:
- https
paths:
  /:
    x-amazon-apigateway-any-method:
      produces:
      - application/json
      responses:
        200:
          description: 200 response
          schema:
            $ref: "#/definitions/Empty"
      x-amazon-apigateway-integration:
        responses:
          default:
            statusCode: 200
        uri: arn:aws:apigateway:YOUR_AWS_REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:YOUR_AWS_REGION:YOUR_ACCOUNT_ID:function:${stageVariables.ServerlessExpressLambdaFunctionName}/invocations
        passthroughBehavior: when_no_match
        httpMethod: POST
        type: aws_proxy
    options:
      consumes:
      - application/json
      produces:
      - application/json
      responses:
        200:
          description: 200 response
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: string
            Access-Control-Allow-Methods:
              type: string
            Access-Control-Allow-Headers:
              type: string
      x-amazon-apigateway-integration:
        contentHandling: CONVERT_TO_TEXT
        responses:
          default:
            statusCode: 200
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
        passthroughBehavior: when_no_match
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        type: mock
  /{proxy+}:
    x-amazon-apigateway-any-method:
      produces:
      - application/json
      parameters:
      - name: proxy
        in: path
        required: true
        type: string
      responses: {}
      x-amazon-apigateway-integration:
        uri: arn:aws:apigateway:YOUR_AWS_REGION:lambda:path/2015-03-31/functions/arn:aws:lambda:YOUR_AWS_REGION:YOUR_ACCOUNT_ID:function:${stageVariables.ServerlessExpressLambdaFunctionName}/invocations
        httpMethod: POST
        type: aws_proxy
    options:
      consumes:
      - application/json
      produces:
      - application/json
      responses:
        200:
          description: 200 response
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: string
            Access-Control-Allow-Methods:
              type: string
            Access-Control-Allow-Headers:
              type: string
      x-amazon-apigateway-integration:
        contentHandling: CONVERT_TO_TEXT
        responses:
          default:
            statusCode: 200
            responseParameters:
              method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Origin: "'https://example.com'"
        passthroughBehavior: when_no_match
        requestTemplates:
          application/json: "{\"statusCode\": 200}"
        type: mock
x-amazon-apigateway-binary-media-types:
  - '*/*'
definitions:
  Empty:
    type: object
    title: Empty Schema

更多信息可以在 GitHub 上找到Internal server error when request method OPTIONS

希望这可以帮助!

我刚刚经历了这个......隐藏在 AWS lambda 文档中关于启用 CORS 的事实是你必须在你的 lambda 中设置 CORS 标头。 所以这里是如何做到这一点:

let payload = {
    statusCode: 400,
    body: JSON.stringify('body'),
    headers: {"Access-Control-Allow-Origin": "*"} // NEED this for API CORS access
};
callback(null, payload);

您必须返回有效的 statusCode 和正文以及标头,否则 API 将无法将您的 lambda 响应转换为 API 响应。

使用 cloudformation 创建无服务器解决方案时,我遇到了同样的问题。 Cloudformation 创建了 API Gateway + Lambda,一切看起来都很好。 但是 OPTIONS 请求返回内部服务器错误。

我不得不去 API 网关并手动发布我的 API 一次。 (尽管它已经发布到产品阶段)然后 OPTIONS 请求起作用了。 我现在可以使用 cloudformation 进行更新。

我正在使用 SAM 模板进行部署,几天来我一直被这个错误困扰。 最后我发现我必须清除 API 网关的“设置”选项卡中的“二进制媒体类型”中的所有内容。

在此处输入图像描述

对我来说,解决方案是改变:

cors: true

cors:
  origin: '*'

我不确定有什么区别,但一个给我内部服务器错误,另一个没有。

您可以在路由索引文件中使用以下代码

app.options(function(req,res){res.send(200);})

这里的 app 是 express 的路由器对象。这会将所有选项请求发送到 200。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM