AWS lambda api网关错误“格式错误的Lambda代理响应”


80

我正在尝试使用AWS Lambda建立一个hello world示例,并通过api网关为其提供服务。我单击了“创建Lambda函数”,这将设置api通道并选择了Blank Function选项。我添加了在AWS网关入门指南中找到的lambda函数:

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

问题是,当我向它发出GET请求时,它返回了502响应{ "message": "Internal server error" }。并且日志显示“由于配置错误,执行失败:Lambda代理响应格式错误”。

Answers:


108

通常,当您看到时Malformed Lambda proxy response,表示您来自Lambda函数的响应与API Gateway期望的格式不匹配,例如

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

如果您未使用Lambda代理集成,则可以登录到API Gateway控制台,然后取消选中Lambda代理集成复选框。

此外,如果您看到的是间歇性的 Malformed Lambda proxy response,则可能意味着Lambda已限制对Lambda函数的请求,并且您需要请求Lambda函数的并发执行限制增加。




这个答案真的很有帮助。谢谢!
Waleed93

48

如果将lambda用作代理,则响应格式应为

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

注意:身体应拉紧


如果“ response”是对象的名称,则无法使用JSON.stringify(response)。像这样离开对我有用。callback(null,response);

4
@Neo您不需要对响应对象进行分类。您需要在响应对象的主体键内对数据进行字符串化
selftaught91'9

出于好奇-为什么身体需要弦化?这是我一直在做的事情的问题,这让我感到困惑-谢谢
安迪·麦卡洛(Andy mccullough)17-10-27

2
其中,statusCode从API网关成功调用仅需进行。
特伦顿

确保身体被拉紧对我有用。非常感谢+1
Kimutai

25

是的,我想这是因为您实际上没有在此处返回正确的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'}))

现在,如果我们使用Access-Control-Allow-Credentials值为true,则不能将'Access-Control-Allow-Origin'值保持为'*'
Santhosh Nagulanchi

1
我观察到它仅支持一个Origin:标头:{“ Access-Control-Allow-Origin”:“ << Single Domain >>”,“ Access-Control-Allow-Credentials”:true // Cookie,授权标头使用HTTPS},
Santhosh Nagulanchi

6

AWS文档

在Node.js的Lambda函数中,要返回成功的响应,请调用callback(null,{“ statusCode”:200,“ body”:“ results”})。要抛出异常,请调用callback(new Error('internal server error'))。对于客户端错误,例如缺少必需的参数,您可以调用callback(null,{“ statusCode”:400,“ body”:“ Missing parameters of ...”})以返回错误而不会引发例外。


5

对于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': ''

3

一个非常非常特殊的情况,如果您直接传递标头,则可能会有此标头:

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

但是亚马逊需要这样:

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


3

对于在响应看起来有效时仍在挣扎的其他任何人。这不起作用:

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'
})

同样,似乎在响应对象上不允许出现多余的键。


3

如果您通过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
}

3

我已经尝试了以上所有建议,但没有body价值时却无济于事String

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

3

.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! :)"}

1
OMG,非常感谢,您花了几个小时试图弄清楚如何在响应中获得标头,才救了我。我尝试了纯JSON,但没有用。我尝试了键值对,但是没有用。字典是必经之路!谢谢!
米沙(Misha)

1

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


0

如果上述方法对任何人都无效,尽管正确设置了响应变量,我还是遇到了此错误。

我正在使用函数调用RDS数据库。原来,导致该问题的原因是该数据库上的安全组规则(入站)。

您可能想限制可以访问该API的IP地址,但是如果您想使其快速/肮脏地工作以测试该更改是否可以解决该问题,可以将其设置为接受所有操作(您也可以设置在端口上也可以接受所有端口,但在此示例中我没有这样做:

在此处输入图片说明


0

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

由于set-cookie标头可以而且确实以倍数形式出现,因此它们在http.request.callback.response中表示为set-cookie具有Arrayof Strings值的键,而不是单个String。虽然这对开发人员有效,但AWS API Gateway无法理解它,并引发“格式错误的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)
}

注意,...以上并不表示Yada Yada Yada。这是ES6传播算子


0

这是另一种方法。在您的API网关集成请求和响应中配置映射模板。转到IntegrationRequest-> MappingTemplate->选择“当没有定义模板时”->为内容类型输入application / json。然后,您不必显式发送json。甚至您在客户端得到的响应也可以是纯字符串。


0

函数响应的格式是此错误的根源。为了让API Gateway处理Lambda函数的响应,该响应必须是JSON,格式为:

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

这是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/


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
}

0

如果您刚接触AWS,只是希望您的URL有效,

如果尚未为Lambda函数创建触发器,请在Lambda Functions应用中导航至该函数,然后选择API Gateway创建触发器。

导航到API Gateway App->选择您特定的Lambda的API Gateway(方法执行)->单击INTEGRATION Request->取消选中“使用Lambda代理集成”(复选框)。

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

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

从日志中选择URL,然后使用POST / GET Tool(邮递员),然后选择身份验证作为AWS签名-在邮递员请求中提供身份验证密钥(AccessKey和SecretKey),并将AWS区域和服务名称作为lambda。

PS:这可能仅对初学者有所帮助,并且可能与其他人无关。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.