部署时出现502带有API Gateway + Lambda的“内部服务器错误”

时间:2019-12-09 13:44:38

标签: amazon-web-services aws-lambda aws-api-gateway serverless-framework

我正在使用API​​-网关+ Lambda组合来处理POST请求。我正在使用Node + Serverless Framework。

当我脱机运行无服务器时,我能够发送POST请求并将数据存储在S3上。但是,当我部署它并运行相同的POST请求时,我收到“ 502 Internal Server Error”消息。因为它可以在本地运行,但不能在生产环境中使用,所以我很确定我遇到了一些权限/配置问题。

    saveToS3(newData)
      .then(result => {
        callback(null, {
          statusCode: 200,
          headers: { 'Content-Type': 'application/json' },
          body: "Successfully added data!"
        });
      })
      .catch(e => callback(null, { statusCode: 500, body: JSON.stringify(e) }));

我检查过的内容

  • 响应主体是字符串
  • 在响应中包括状态代码,正文,响应头
  • 使用回调模式返回我的响应(请参见上文)

没有检查的内容:

  • 一个可能的原因是我的API网关api无权调用lambda函数。如何在serverless.yml文件中进行设置?

我的yml:

service: myService

provider:
  name: aws
  runtime: nodejs12.x

  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "s3:GetObject"
        - "s3:PutObject"
      Resource: "arn:aws:s3:::myS3Bucket/*"

functions:
  saveToS3:
    handler: handler.saveToS3
    events:
      - http:
          path: users
          method: post
          cors: true
plugins:
  - serverless-offline

resources:
 Resources:
   NewResource:
     Type: AWS::S3::Bucket
     Properties:
       BucketName: myS3Bucket

3 个答案:

答案 0 :(得分:1)

如果使用代理集成,则需要小心,因为对于每种可能的语法错误,它将引发内部服务器错误。

catch(e => callback(null, { statusCode: 500, body: JSON.stringify(e) }));

错误可以不在此处设置标题吗? 如果不是这样,可能是语法错误。

答案 1 :(得分:0)

发现了这个问题,面色苍白,因为我花了几个小时才找到它。

我有两个问题:

  • 我的主要lambda函数前面有一个“异步”,但是我正在用回调实现它。删除“异步”即可解决。

  • 我的响应格式缺少“标头”和“ isBase64Encoded”字段。包括该命令可以消除502错误(请参见下文)。

有用的链接: -https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format -(如果您使用的是无服务器框架)https://github.com/dherault/serverless-offline/issues/405

如果使用API​​ Gateway ,请确保您的lambda函数的响应类似于下面的代码片段。否则,它将引发“ 502-Lambda函数格式错误”错误。

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}

答案 2 :(得分:0)

在我们的例子中,我们使用无服务器 + API 网关 + Lambda。我们的主要 app.ts 导出一个由无服务器包装的异步处理程序。例如(EnvironmentService 只是环境配置的服务层):

const allowedBinaryMimeTypes = EnvironmentService.getFileMimeTypesAllowed();
...
const handler = serverless(app, { binary: allowedBinaryMimeTypes });

在修改任何代码之前,502 错误网关错误日志显示了这一点 (AWS CloudWatch):

enter image description here

enter image description here

我们的解决方案是覆盖 serverless.yml 中的默认 aws 提供程序超时:

where to add override variable

S3Service 文件(调用 getObject):

    static async getObject(type: string, pathParams: APIGatewayProxyEventPathParameters): Promise<any> {
        const params = await this.setRequestParams(type, pathParams.id, pathParams.fileName);

        try {
            // get S3 object/file
            const data = await S3.getObject(params).promise();

            // some bug with AWS converting JPG objects to JPEGg
            const contentType = data.ContentType === 'image/jpeg' ? 'image/jpg' : data.ContentType;

            return {
                statusCode: 200,
                headers: {
                    'Access-Control-Allow-Headers': 'Content-Type',
                    'Access-Control-Allow-Origin': '*', // Required for CORS support to work
                    'Access-Control-Allow-Methods': 'OPTIONS,GET',
                    'Content-Type': contentType
                },
                body: data.Body.toString('base64'),
                isBase64Encoded: true
            };
        } catch (err) {
            console.error(err);
            throw err;
        }
    }