programing

AWS lambda API 게이트웨이 오류 "형식이 잘못된 Lambda 프록시 응답"

megabox 2023. 9. 6. 21:58
반응형

AWS lambda API 게이트웨이 오류 "형식이 잘못된 Lambda 프록시 응답"

AWS lambda로 hello world 예제를 설정하고 api 게이트웨이를 통해 서비스하려고 합니다.apatway를 설정하고 Blank Function 옵션을 선택하는 "Create a Lambda Function"을 클릭했습니다.AWS 게이트웨이 시작 가이드에 있는 람다 함수를 추가했습니다.

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

응답 는 GET 502 이 입니다 을 입니다 을 이 는 { "message": "Internal server error" }에 "오류로 : 의 람다 응답이라고 표시됩니다 그리고 로그에는 "구성 오류로 인한 실행 실패: 잘못된 형식의 Lambda proxy response"라고 기록되어 있습니다.

보통 볼 때는.Malformed Lambda proxy response은 당신의 합니다. , 의 로부터의 의 이 가 합니다 하는 을 과 하지 은 합니다 을 하지 가 과 은 하는

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

Lambda 프록시 통합을 사용하지 않는 경우 API Gateway 콘솔에 로그인하고 Lambda 프록시 통합 확인란의 선택을 취소할 수 있습니다.

또한 간헐적으로 발생하는 경우Malformed Lambda proxy responseLambda에 할 수 , 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': ''

잘못된 핸들러 코드로 인해 문제가 발생했습니다.

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

다소 혼란스러운 API Gateway 응답 로그를 조사하여 힌트를 얻었습니다.

> 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가 비동기/대기/약속 또는 콜백 리턴 방법을 사용할 것을 예상하지 못한 채 코드의 복잡성을 줄여줍니다.

AWS 문서에서

Node.js의 람다 함수에서 성공적인 응답을 반환하려면 콜백(null, {"statusCode": 200, "body": "results"})을 호출합니다.예외를 삭제하려면 콜백(new Error('내부 서버 오류')을 호출합니다.클라이언트 측 오류(예: 필수 매개 변수가 누락된 경우 콜백(null, {"statusCode": 400, "body": "missing parameter of ...")을 호출할 수 있습니다."}) 예외를 두지 않고 오류를 반환합니다.

.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;

람다로부터의 응답은 다음과 같습니다.

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

API 게이트웨이의 응답은 다음과 같습니다.

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

의 을 해 이 이 의 해 body이다가 .String

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

응답이 유효한 것처럼 보일 때 어려움을 겪는 모든 사용자에게 해당합니다.작동하지 않습니다.

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

또한 응답 개체에 추가 키가 있을 수 없는 것으로 보입니다.

아주 특별한 경우로, 헤더를 직접 전달하면 다음과 같은 헤더가 나올 가능성이 있습니다.

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

하지만 아마존은 이것을 필요로 합니다.

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

바둑은 AWS Lambda를 사용하는 경우는events.APIGatewayProxyResponse.

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

은 의 에 이 에 JSON,식,만)STRING형식은 Lambda 프록시를 API Gateway와 통합할 수 있습니다.

그래서 당신의 오래된 반응체를 싸세요.JSON.stringify().

CloudFormation AWS::Serverless::에서 ServerlessExpressLambdaFunctionName 변수를 실수로 제거하여 이 오류가 발생했습니다.API 리소스.여기서의 맥락은 "AWS Lambda 및 Amazon API Gateway 위에 기존 Node.js 응용 프로그램 프레임워크를 사용하여 서버리스 응용 프로그램 및 REST API 실행"입니다.

위의 내용이 누구에게도 통하지 않을 경우, 응답 변수를 올바르게 설정했음에도 불구하고 이 오류를 범했습니다.

저는 제 기능에 있는 RDS 데이터베이스에 전화를 걸고 있었습니다.문제의 원인은 해당 데이터베이스의 보안 그룹 규칙(인바운드)인 것으로 나타났습니다.

API에 액세스할 수 있는 IP 주소를 제한해야 할 수도 있지만, 변경 사항이 수정되면 테스트를 위해 빨리 작동하거나 더럽게 작동하도록 하려면 모든 포트를 허용하도록 설정할 수 있습니다(포트의 범위를 모든 포트를 허용하도록 설정할 수도 있지만, 이 예에서는 이 작업을 수행하지 않았습니다.

enter image description here

response"은 "Malformed Lambda proxy response"입니다.headers가 아닌{String: String, ...}키/값 쌍.

set-cookie.request.callback.response의 http.request.callback.response의 http.request.callback.response의 http.request.callback.response의 http.response의set-cookie키는 싱글이 아닌 가치가 있습니다.이것은 개발자들에게는 효과가 있지만 AWS API Gateway는 이를 이해하지 못하고 "Malformed Lambda proxy response" 오류를 발생시킵니다.

제 해결책은 다음과 같은 것을 하는 것입니다.

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 -> "Template가 정의되어 있지 않을 때" -> application/json을 컨텐츠 유형으로 선택합니다.그렇다면 json을 명시적으로 보낼 필요는 없습니다.고객에게 받는 응답도 간단한 문자열이 될 수 있습니다.

파이썬 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 Function에 대한 트리거를 생성하지 않은 경우 Lambda Functions app에서 해당 기능으로 이동하고 API Gateway를 선택하여 트리거를 생성합니다.

API Gateway App으로 이동 -> 특정 Lambda의 API Gateway 선택(Method 실행) -> INTEGATION 요청 클릭 -> "Lambda Proxy integration 사용" 선택 취소(체크박스)

그리고 "<-Method Execution"을 클릭한 후 Test Client 섹션을 클릭합니다.옵션을 제공하고 테스트 버튼을 클릭합니다.성공적인 반응을 볼 수 있을 겁니다.

그래도 성공적인 응답을 얻을 수 없으면 올바른 버전에 대한 별칭을 만듭니다(Lambda Function에 여러 버전이 있는 경우).

로그에서 URL을 선택한 후 POST/GET Tool(포스트맨)을 사용하여 인증을 AWS Signature - AWS Region & Service Name에서 인증키(AccessKey & SecretKey)를 lambda로 제공합니다.

추신: 이것은 초보자들에게만 도움이 될 수도 있고 다른 사람들과는 무관할 수도 있습니다.

함수 응답 형식이 이 오류의 원인입니다.API Gateway가 Lambda 함수의 응답을 처리하려면 다음 형식의 응답이 JSON이어야 합니다.

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

Node.js의 응답 형식이 정확한 함수 예는 다음과 같습니다.

exports.fault = (이벤트, 컨텍스트, 콜백) => {

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);

};

참조:Lambda proxy 통합으로 API Gateway REST API의 HTTP 502 오류를 해결하려면 어떻게 해야 합니까?

언급URL : https://stackoverflow.com/questions/43708017/aws-lambda-api-gateway-error-malformed-lambda-proxy-response

반응형