[英]Malformed Lambda proxy response with AWS Lambda and API Gateway NodeJs
[英]AWS lambda api gateway error "Malformed Lambda proxy response"
我正在嘗試使用 AWS lambda 設置一個 hello world 示例並通過 api 網關為其提供服務。 我單擊“創建 Lambda 函數”,它設置了 api 網關並選擇了空白函數選項。 我添加了AWS 網關入門指南中的 lambda 函數:
exports.handler = function(event, context, callback) {
callback(null, {"Hello":"World"}); // SUCCESS with message
};
問題是當我向它發出 GET 請求時,它會返回 502 響應{ "message": "Internal server error" }
。 並且日志顯示“由於配置錯誤,執行失敗:格式錯誤的 Lambda 代理響應”。
通常,當您看到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 函數的並發執行限制。
如果 lambda 用作代理,則響應格式應為
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
是的,所以我認為這是因為您實際上並沒有在那里返回正確的 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'}))
對於 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': ''
來自AWS 文檔
在 Node.js 的 Lambda 函數中,要返回成功的響應,請調用 callback(null, {"statusCode": 200, "body": "results"})。 要拋出異常,請調用 callback(new Error('internal server error'))。 對於客戶端錯誤,例如缺少必需的參數,您可以調用 callback(null, {"statusCode": 400, "body": "Missing parameters of ..."}) 返回錯誤而不拋出例外。
我已經嘗試了以上所有建議,但是當body
值不是String
時它不起作用
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify({
success: true
}),
isBase64Encoded: false
};
只是一段.net core和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! :)"}
我遇到了這個問題,它源於一個看起來完全沒問題的無效處理程序代碼:
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 或回調返回方法。
一個非常特殊的情況,如果您直接傳遞標頭,則有可能擁有此標頭:
"set-cookie": [ "........" ]
但亞馬遜需要這個:
"set-cookie": "[ \\\\"........\\\\" ]"
對於在響應似乎有效時掙扎的其他任何人。 這不起作用:
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'
})
此外,似乎不允許在響應對象上存在額外的鍵。
如果您將 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
}
我遇到此錯誤是因為我不小心從 CloudFormation AWS::Serverless::Api 資源中刪除了變量 ServerlessExpressLambdaFunctionName。 這里的上下文是https://github.com/awslabs/aws-serverless-express “使用現有的 Node.js 應用程序框架在 AWS Lambda 和 Amazon API 網關之上運行無服務器應用程序和 REST API”
“Malformed Lambda 代理響應”錯誤的一個常見原因是headers
不是{String: String, ...}
鍵/值對。
由於set-cookie
標頭可以而且確實以多個形式出現,因此它們在 http.request.callback.response 中表示為set-cookie
鍵,它具有一個Strings
Array
值而不是單個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 擴展運算符。
這是另一種方法。 在 API 網關集成請求和響應中配置映射模板。 轉到 IntegrationRequest -> MappingTemplate -> 選擇“當沒有定義模板時”-> 為內容類型鍵入 application/json。 然后您不必顯式發送 json。 甚至您在客戶端得到的響應也可以是純字符串。
函數響應的格式是此錯誤的來源。 為了讓 API Gateway 處理 Lambda 函數的響應,響應必須是以下格式的 JSON:
{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "body": "..." }
這是 Node.js 中的示例函數,其響應格式正確:
export.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/
蟒蛇 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 正常工作,
如果您尚未為 Lambda 函數創建觸發器,請導航到 Lambda 函數應用程序中的函數並選擇 API 網關創建觸發器。
導航到 API 網關應用程序 -> 選擇您特定的 Lambda 的 API 網關(方法執行)-> 單擊集成請求 ->取消選中“使用 Lambda 代理集成” (復選框)。
然后單擊“ <-Method Execution ”並單擊“測試客戶端”部分。 提供選項並單擊測試按鈕。 您應該會看到成功響應。
如果您仍然無法獲得成功響應,請為正確的版本創建別名(如果您在 Lambda 函數中有多個版本)
從日志中選擇 URL 並使用您的 POST/GET 工具(郵遞員)並選擇身份驗證作為 AWS 簽名 - 在郵遞員請求中提供您的身份驗證密鑰(訪問密鑰和秘密密鑰),並將 AWS 區域和服務名稱作為 lambda。
PS:這可能只對初學者有幫助,對其他人可能無關緊要。
您返回的正文很可能是JSON<\/code>格式,但 Lambda 代理與 API Gateway 的集成只允許使用
STRING<\/code>格式。
所以用
JSON.stringify()<\/code>包裝你的舊響應體。
"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.