我正在尝试使用AWS lambda建立一个hello world示例并通过api网关提供它。我点击了“创建一个Lambda函数”,它设置了api gatway并选择了Blank Function选项。我添加了AWS gateway getting started guide上的lambda函数:
exports.handler = function(event, context, callback) {
callback(null, {"Hello":"World"}); // SUCCESS with message
};
问题在于,当我向它发出GET请求时,它会返回502响应{ "message": "Internal server error" }
。并且日志显示“由于配置错误导致执行失败:格式错误的Lambda代理响应”。
答案 0 :(得分:68)
通常,当您看到Malformed Lambda proxy response
时,这意味着您的Lambda函数的响应与API网关期望的格式不匹配,就像这样
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
如果您未使用Lambda代理集成,则可以登录API Gateway控制台并取消选中Lambda代理集成复选框。
此外,如果您看到间歇Malformed Lambda proxy response
,则可能意味着Lambda会限制对您的Lambda函数的请求,并且您需要请求Lambda函数的并发执行限制增加。
答案 1 :(得分:36)
如果lambda用作代理,则响应格式应为
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
答案 2 :(得分:22)
是的,所以我认为这是因为您实际上没有在那里返回正确的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'}))
答案 3 :(得分:6)
来自AWS docs
在Node.js的Lambda函数中,要返回成功的响应,请调用 callback(null,{“statusCode”:200,“body”:“results”})。抛出一个 异常,调用回调(新错误('内部服务器错误'))。为一个 客户端错误,例如,缺少必需参数,您可以调用 callback(null,{“statusCode”:400,“body”:“缺少参数 ...“}}返回错误而不抛出异常。
答案 4 :(得分:3)
我遇到了这个问题,它源于无效的处理程序代码,看起来完全没问题:
exports.handler = (event, context) => {
return {
isBase64Encoded: false,
body: JSON.stringify({ foo: "bar" }),
headers: {
'Access-Control-Allow-Origin': '*',
},
statusCode: 200,
};
}
我从检查有点混乱的 API 网关响应日志中得到了提示:
> Endpoint response body before transformations: null
修复它的方法是要么
async
关键字(异步函数隐式返回一个 Promise):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 期望使用 async/await/ Promise 或回调返回方法。
答案 5 :(得分:2)
一个非常特殊的情况,如果你直接传递标题,你有可能有这个标题:
web: gunicorn main_loop:app
但亚马逊需要这个:
"set-cookie": [ "........" ]
答案 6 :(得分:2)
适用于在响应看起来有效时仍在挣扎的其他任何人。这不起作用:
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'
})
此外,似乎在响应对象上不允许出现多余的键。
答案 7 :(得分:2)
如果将https://github.com/aws/aws-lambda-go与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
}
答案 8 :(得分:1)
我已经尝试了以上所有建议,但是在body
的值不是String
时却无效了
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify({
success: true
}),
isBase64Encoded: false
};
答案 9 :(得分:1)
我遇到此错误,因为我意外地从CloudFormation AWS :: Serverless :: Api资源中删除了变量ServerlessExpressLambdaFunctionName。这里的上下文是https://github.com/awslabs/aws-serverless-express“使用您现有的Node.js应用程序框架,在AWS Lambda和Amazon API Gateway之上运行无服务器应用程序和REST API”
答案 10 :(得分:0)
如果上述方法不适用于任何人,尽管正确设置了响应变量,我还是遇到了此错误。
我正在使用函数调用RDS数据库。原来,导致该问题的原因是该数据库上的安全组规则(入站)。
您可能想限制可以访问该API的IP地址,但是如果您想使其快速运行/变脏以测试该更改是否可以解决,则可以将其设置为接受所有此类(您可以还将端口范围设置为也接受所有端口,但在此示例中我没有这样做):
答案 11 :(得分:0)
“格式错误的Lambda代理响应”错误的常见原因是headers
不是{String: String, ...}
键/值对。
由于set-cookie
标头可以并且确实以倍数出现,因此它们被表示
在http.request.callback.response中作为{<1>}的set-cookie
键
Array
值,而不是单个Strings
。虽然这对开发人员有效,但AWS
API网关不理解它,并抛出“格式错误的Lambda代理响应”
错误。
我的解决方案是执行以下操作:
String
请注意,以上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)
}
并不表示 Yada Yada Yada 。是ES6 spread operator。
答案 12 :(得分:0)
.net核心和 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! :)"}
答案 13 :(得分:0)
这是另一种方法。在您的API网关集成请求和响应中配置映射模板。转到IntegrationRequest-> MappingTemplate->选择“当未定义模板时”->为内容类型输入application / json。然后,您不必显式发送json。甚至您在客户端得到的响应也可以是纯字符串。
答案 14 :(得分:0)
函数响应的格式是此错误的根源。为了让API Gateway处理Lambda函数的响应,该响应必须为JSON,格式为:
{ “ isBase64Encoded”:true | false, “ statusCode”:httpStatusCode, “ headers”:{“ headerName”:“ headerValue”,...}, “身体”: ”...” }
这是Node.js中的示例函数,其响应的格式正确:
exports.handler =(事件,上下文,回调)=> {
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/
答案 15 :(得分:0)
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
}
答案 16 :(得分:0)
如果您刚接触AWS,只是希望您的URL有效,
如果尚未为Lambda函数创建触发器,请在Lambda Functions应用中导航至该函数,然后选择API Gateway创建触发器。
导航到API网关应用程序->选择特定的Lambda的API网关(方法执行)->单击INTEGRATION Request-> 取消选中“使用Lambda代理集成” (复选框)。
然后单击“ <-方法执行”,然后单击“测试客户端”部分。提供选项,然后单击测试按钮。您应该会看到成功的响应。
如果仍然无法获得成功响应,请为正确的版本创建别名(如果Lambda函数中有多个版本)
从日志中选择URL,然后使用POST / GET Tool(邮递员)并选择身份验证作为AWS签名-在邮递员请求中提供身份验证密钥(AccessKey和SecretKey),并将AWS区域和服务名称作为lambda。
P.S:这可能仅对初学者有所帮助,并且可能与其他人无关。
答案 17 :(得分:-1)
对于Python3:
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': ''