AWS Lambda api 网关错误“ MalformedLambda 代理响应”

我试图用 AWS lambda 建立一个 hello world 示例,并通过 api 网关为其提供服务。我单击了“ Create a Lambda Function”,它设置了 api 网关并选择了 Blank Function 选项。我添加了 AWS gateway getting started guide上的 lambda 函数:

exports.handler = function(event, context, callback) {
callback(null, {"Hello":"World"});  // SUCCESS with message
};

The issue is that when I make a GET request to it, it's returning back a 502 response { "message": "Internal server error" }. And the logs say "Execution failed due to configuration error: Malformed Lambda proxy response".

76521 次浏览

通常,当您看到 Malformed Lambda proxy response时,这意味着来自 Lambda 函数的响应与 API 网关所期望的格式不匹配,如下所示

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

如果不使用 Lambda 代理集成,可以登录到 API 网关控制台并取消选中 Lambda 代理集成复选框。

Also, if you are seeing intermittent Malformed Lambda proxy response, it might mean the request to your Lambda function has been throttled by Lambda, and you need to request a concurrent execution limit increase on the Lambda function.

是的,所以我认为这是因为您实际上没有返回一个正确的 http 响应,这就是为什么您会得到这个错误。

我个人使用的函数集如下:

    module.exports = {
success: (result) => {
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin" : "*", // Required for CORS support to work
"Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
},
body: JSON.stringify(result),
}
},
internalServerError: (msg) => {
return {
statusCode: 500,
headers: {
"Access-Control-Allow-Origin" : "*", // Required for CORS support to work
"Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
},
body: JSON.stringify({
statusCode: 500,
error: 'Internal Server Error',
internalError: JSON.stringify(msg),
}),
}
}
} // add more responses here.

然后你就这么做了:

var responder = require('responder')


// some code


callback(null, responder.success({ message: 'hello world'}))

如果使用 lambda 作为代理,那么响应格式应该是

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

Note : The body should be stringified

来自 AWS 文件

在 Node.js 中的 Lambda 函数中,要返回一个成功的响应,请调用 回调(null,{“ statusCode”: 200,“ body”: “ result”}) 异常,调用回调(new Error (‘ Internal server Error’)) 客户端错误,例如,缺少必需的参数,您可以调用 回调(null,{“ statusCode”: 400,“ body”: “丢失的参数 ..."}) to return the error without throwing an exception.

之所以出现这个错误,是因为我不小心从 CloudFormentAWS: : Serverless: : Api 资源中删除了变量 Serverless ExpressLambdaFunctionName。这里的上下文是 https://github.com/awslabs/aws-serverless-express“使用您现有的 Node.js 应用程序框架,在 AWS Lambda 和 Amazon API Gateway 之上运行无服务器应用程序和 REST API”

A very very special case, if you pass the headers directly there is a chance you have this header:

"set-cookie": [ "........" ]

但亚马逊需要这些:

"set-cookie": "[ \\"........\\" ]"

如果上面的方法对任何人都不起作用,那么尽管正确设置了响应变量,我还是遇到了这个错误。

我正在函数中调用 RDS 数据库。结果发现,导致问题的是该数据库上的安全组规则(入站)。

你可能想要限制可以访问 API 的 IP 地址,但是如果你想让它快速工作/脏测试出来,如果修复它,你可以设置它接受所有像这样(你也可以设置接受所有端口的端口范围,但我没有这样做在这个例子) :

enter image description here

对于那些在回答看起来有效的时候挣扎的人来说,这是行不通的:

callback(null,JSON.stringify( {
isBase64Encoded: false,
statusCode: 200,
headers: { 'headerName': 'headerValue' },
body: 'hello world'
})

但这个可以:

callback(null,JSON.stringify( {
'isBase64Encoded': false,
'statusCode': 200,
'headers': { 'headerName': 'headerValue' },
'body': 'hello world'
})

Also, it appears that no extra keys are allowed to be present on the response object.

如果使用 Go 和 https://github.com/aws/aws-lambda-go,则必须使用 events.APIGatewayProxyResponse

func hello(ctx context.Context, event ImageEditorEvent) (events.APIGatewayProxyResponse, error) {
return events.APIGatewayProxyResponse{
IsBase64Encoded: false,
StatusCode:      200,
Headers:         headers,
Body:            body,
}, nil
}

我已经尝试了以上所有的建议,但它不工作,而 body值不是 String

return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify({
success: true
}),
isBase64Encoded: false
};

对于 Python 3:

import json


def lambda_handler(event, context):
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({
'success': True
}),
"isBase64Encoded": False
}

注意,不需要设置 body,它可以是空的:

        'body': ''

“畸形 Lambda 代理响应”错误的一个常见原因是 headers不是 {String: String, ...}键/值对。

因为 set-cookie标头可以并且确实以多个形式出现,所以它们被表示出来 在 http.request.callback.response 中,作为具有 < strong > Arrayset-cookie键 取代 单一 String的是 Strings 值 API 网关不理解它,抛出一个“畸形 Lambda 代理响应” 错误。

我的解决办法是这样做:

function createHeaders(headers) {
const singleValueHeaders = {}
const multiValueHeaders = {}
Object.entries(headers).forEach(([key, value]) => {
const targetHeaders = Array.isArray(value) ? multiValueHeaders : singleValueHeaders
Object.assign(targetHeaders, { [key]: value })
})


return {
headers: singleValueHeaders,
multiValueHeaders,
}
}


var output = {
...{
"statusCode": response.statusCode,
"body": responseString
},
...createHeaders(response.headers)
}

请注意,上面的 ...并不意味着 等等,等等。它是 ES6 spread operator

Just a piece of code for . net core and C # :

using Amazon.Lambda.APIGatewayEvents;
...
var response = new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = JsonConvert.SerializeObject(new { msg = "Welcome to Belarus! :)" }),
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
return response;

Lambda 的回应是:

{"statusCode":200,"headers":{"Content-Type":"application/json"},"multiValueHeaders":null,"body":"{\"msg\":\"Welcome to Belarus! :)\"}","isBase64Encoded":false}

来自 api 网关的回应将是:

{"msg":"Welcome to Belarus! :)"}

还有一个办法。在 API 网关集成请求和响应中配置映射模板。转到 IntegrationRequest-> MappingTemplate-> select“ When there are no template Definition”-> type application/json for content-type。那么就不必显式地发送 json。甚至您在客户端得到的响应也可以是一个简单的字符串。

函数响应的格式是此错误的来源。对于 API 网关来处理 Lambda 函数的响应,响应必须是以下格式的 JSON:

{ “ isBase64编码”: true | false, “ statusCode”: httpStatusCode, “ headers”: {“ headerName”: “ headerValue”,... } , “尸体”: “ ...” }

下面是 Node.js 中格式正确的响应函数示例:

exports.handler = (event, context, callback) => {

var responseBody = {
"key3": "value3",
"key2": "value2",
"key1": "value1"
};


var response = {
"statusCode": 200,
"headers": {
"my_header": "my_value"
},
"body": JSON.stringify(responseBody),
"isBase64Encoded": false
};
callback(null, response);

};

档号: https://aws.amazon.com/premiumsupport/knowledge-center/malformed-502-api-gateway/

Python 3.7

之前

{
"isBase64Encoded": False,
"statusCode": response.status_code,
"headers": {
"Content-Type": "application/json",
},
"body": response.json()
}

之后

{
"isBase64Encoded": False,
"statusCode": response.status_code,
"headers": {
"Content-Type": "application/json",
},
"body": str(response.json()) //body must be of string type
}

如果您刚刚接触 AWS,只是希望您的 URL 能够正常工作,

If you haven't created a trigger for your Lambda Function, navigate to the function in Lambda Functions app and create trigger choosing API Gateway.

导航到 API 网关应用程序-> 选择特定 Lambda 的 API 网关(方法执行)-> 单击 INTEGRATION Request-> Uncheck "Use Lambda Proxy integration"(复选框)。

然后点击“ <-方法执行”并点击“测试客户端”部分。提供选项并单击测试按钮。您应该会看到一个成功的响应。

如果仍然无法获得成功响应,请为正确的版本创建别名(如果 Lambda 函数中有多个版本)

从日志中选择 URL,使用 POST/GET 工具(Postman)并选择身份验证作为 AWS 签名——在邮递员请求中提供身份验证密钥(AccessKey & Secretariat Key) ,并将 AWS 区域和服务名称作为 lambda。

附注: 这可能只对初学者有帮助,对其他人可能无关紧要。

我有这个问题,它起源于一个无效的处理程序代码 看起来完全罚款:

exports.handler = (event, context) => {
return {
isBase64Encoded: false,
body: JSON.stringify({ foo: "bar" }),
headers: {
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
};
}

I got the hint from examining the somewhat confusing API Gateway response logs:

> Endpoint response body before transformations: null

解决问题的方法是

  • 添加 async关键字(异步函数隐式返回一个 ) :
exports.handler = async (event, context) => {
return {
isBase64Encoded: false,
body: JSON.stringify({ foo: "bar" }),
headers: {
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
};
}
  • 返回承诺:
exports.handler = (event, context) => {
return new Promise((resolve) => resolve({
isBase64Encoded: false,
body: JSON.stringify({ foo: "bar" }),
headers: {
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
}));
}
  • 使用回调:
exports.handler = (event, context, callback) => {
callback({
isBase64Encoded: false,
body: JSON.stringify({ foo: "bar" }),
headers: {
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
});
}

我的处理程序之前声明为 async,但从未使用过 await,所以我删除了 async关键字以降低代码的复杂性,而没有意识到 Lambda 期望使用异步/等待/承诺或回调返回方法。

返回的主体很可能是 JSON格式,但是只有 STRING格式允许 Lambda 代理与 API 网关集成。

所以用 JSON.stringify()包裹你的旧响应体。