部署时使用 API 网关 + Lambda 的 502 "Internal Server Error"
502 "Internal Server Error" with API Gateway + Lambda when deploying
我正在使用 API-网关 + Lambda 组合来处理 POST 请求。我正在使用节点 + 无服务器框架。
当我 运行 无服务器脱机时,我能够发送 POST 请求并将我的数据存储在 S3 上。但是当我部署它和 运行 相同的 POST 请求时,我收到“502 内部服务器错误”消息。因为它在本地工作但不在生产环境中工作,所以我很确定我遇到了一些 permission/config 问题。
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) }));
我检查过的内容:
- 响应主体是一个字符串
- 在响应中包含状态码、正文、响应头
- 使用回调模式 return 我的回复(见上文)
我还没有检查的内容:
- 一个可能的原因是我的 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
如果您使用代理集成,您需要小心,因为对于每一个可能的语法错误,它都会引发内部服务器错误。
catch(e => callback(null, { statusCode: 500, body: JSON.stringify(e) }));
会不会是这里没有设置headers的错误?
如果不是,则可能是语法错误。
找到问题了,因为我花了好几个小时才找到它。
我有两个问题:
我的主要 lambda 函数前面有一个 "async",但我是通过回调来实现它的。删除 "async" 修复它。
我的回复格式缺少 "headers" 和 "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 网关, 确保您的 lambda 函数的响应类似于下面的代码片段。否则它将抛出“502 - 格式错误的 Lambda 函数”错误。
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}
在我们的例子中,我们使用无服务器 + API 网关 + Lambda。我们的主要 app.ts
导出一个由无服务器包装的异步处理程序。例如(EnvironmentService
只是环境配置的服务层):
const allowedBinaryMimeTypes = EnvironmentService.getFileMimeTypesAllowed();
...
const handler = serverless(app, { binary: allowedBinaryMimeTypes });
在修改任何代码之前,502 错误网关错误日志显示如下 (AWS CloudWatch):
我们的解决方案是覆盖 serverless.yml 中的默认 aws 提供商超时:
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;
}
}
我正在使用 API-网关 + Lambda 组合来处理 POST 请求。我正在使用节点 + 无服务器框架。
当我 运行 无服务器脱机时,我能够发送 POST 请求并将我的数据存储在 S3 上。但是当我部署它和 运行 相同的 POST 请求时,我收到“502 内部服务器错误”消息。因为它在本地工作但不在生产环境中工作,所以我很确定我遇到了一些 permission/config 问题。
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) }));
我检查过的内容:
- 响应主体是一个字符串
- 在响应中包含状态码、正文、响应头
- 使用回调模式 return 我的回复(见上文)
我还没有检查的内容:
- 一个可能的原因是我的 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
如果您使用代理集成,您需要小心,因为对于每一个可能的语法错误,它都会引发内部服务器错误。
catch(e => callback(null, { statusCode: 500, body: JSON.stringify(e) }));
会不会是这里没有设置headers的错误? 如果不是,则可能是语法错误。
找到问题了,因为我花了好几个小时才找到它。
我有两个问题:
我的主要 lambda 函数前面有一个 "async",但我是通过回调来实现它的。删除 "async" 修复它。
我的回复格式缺少 "headers" 和 "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 网关, 确保您的 lambda 函数的响应类似于下面的代码片段。否则它将抛出“502 - 格式错误的 Lambda 函数”错误。
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}
在我们的例子中,我们使用无服务器 + API 网关 + Lambda。我们的主要 app.ts
导出一个由无服务器包装的异步处理程序。例如(EnvironmentService
只是环境配置的服务层):
const allowedBinaryMimeTypes = EnvironmentService.getFileMimeTypesAllowed();
...
const handler = serverless(app, { binary: allowedBinaryMimeTypes });
在修改任何代码之前,502 错误网关错误日志显示如下 (AWS CloudWatch):
我们的解决方案是覆盖 serverless.yml 中的默认 aws 提供商超时:
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;
}
}