AWS API网关OPTIONS请求返回500错误

时间:2017-07-09 12:34:26

标签: node.js amazon-web-services aws-lambda aws-api-gateway

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

似乎我的API通过API网关正常工作。我的帖子和get方法运行正常。但是,我需要支持CORS。我的应用程序应该返回对OPTIONS请求的正确CORS响应,但它不适用于AWS。

最终,无论我做什么,我都会收到500个选项请求回复。我无法弄清楚如何获得有关这500个错误的任何信息。我不确定是什么导致了他们。

这是500响应的正文{"message": "Internal server error"}

这些是响应标题:

  

内容长度:36

     

内容类型:application / JSON

     

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

     

状态:500

     

via:1.1 9af17e5a616bfc9ac07fc7e415ade9e6.cloudfront.net(CloudFront)

     

的x AMZ-CF-ID:1_AZmkLqf1rjkog2MRtvcBAe54aIZdPWmNApBTwG48Af-v_g9WHkZw ==

     

的x AMZN-的requestId:ec216a62-64cf-11E7-ad2b-4f1e96508dba

     

x-cache:来自cloudfront的错误

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

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

如果有什么我可以查看或正在调试此问题?

编辑:

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

CloudWatch configuration for the API Gateway

在执行此操作后,我在CloudWatch中看到了这两个网关外观日志:

enter image description here

我一直在使用prod所以我点击该链接并看到:

enter image description here

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

enter image description here

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

那么,我是否正确设置了日志记录?我在寻找合适的地方吗?

6 个答案:

答案 0 :(得分:1)

我刚刚完成了这个...隐藏在AWS lambda docs中启用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响应。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

对于仍然因aws-serverless-express而面临OPTIONS 500错误的人,解决方案是将contentHandling: CONVERT_TO_TEXT添加到Swagger template的OPTIONS方法中

这是包含 / / {proxy +} 路径

的招摇模板文件
---
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

上找到

希望这会有所帮助!

答案 3 :(得分:0)

我和@scopchanov有类似的问题。

在我的AWS Lambda + API网关+无服务器框架1.42.3 + Express.js项目中有效的是:

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

    /// AWS API Gateway CORS(OPTIONS)支持是否有问题? app.use(cors({credentials:true}))); app.options(“ *”,cors());

  2. 请勿在API网关中启用CORS,即不要在serverless.yml中进行此操作:

    • http:   方法:任何   路径:“ {proxy +}”   #将导致{“ message”:“内部服务器错误”}   #cors:是

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

cors: true中,OPTIONS请求将以{"message": "Internal server error"}响应(无论Lambda函数做什么,它似乎都是由API Gateway直接发送的,或者是错误的MOCK集成发送的)

答案 4 :(得分:0)

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

cors: true

cors:
  origin: '*'

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

答案 5 :(得分:-1)

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

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

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