Programing

Amazon API Gateway에서 반환 한 http 상태 코드를 변경하는 방법이 있습니까?

lottogame 2020. 9. 13. 11:37
반응형

Amazon API Gateway에서 반환 한 http 상태 코드를 변경하는 방법이 있습니까?


예를 들어 잘못된 매개 변수에 대해 특정 400 오류를 반환하거나 람다 함수 호출로 인해 생성이 발생했을 때 201을 반환하려는 경우.

다른 http 상태 코드를 갖고 싶지만 람다 함수가 오류를 반환하더라도 api 게이트웨이가 항상 200 상태 코드를 반환하는 것처럼 보입니다.


2016 년 9 월 20 일에 업데이트

Amazon은 마침내 Lambda 프록시 통합을 사용하여이를 쉽게 만들었습니다 . 이를 통해 Lambda 함수가 적절한 HTTP 코드 및 헤더를 반환 할 수 있습니다.

let response = {
    statusCode: '400',
    body: JSON.stringify({ error: 'you messed up!' }),
    headers: {
        'Content-Type': 'application/json',
    }
};

context.succeed(response);

API Gateway에서 작별 요청 / 응답 매핑!

옵션 2

aws-serverless-express를 사용하여 기존 Express 앱을 Lambda / API Gateway와 통합합니다 .


사용자 지정 HTTP 상태 코드 및 사용자 지정을 반환하는 가장 빠른 방법은 다음과 같습니다 errorMessage.

API Gateway 대시 보드에서 다음을 수행합니다.

  1. 에서 방법 당신을위한 자원 , 클릭 방법 응답
  2. 에서 HTTP 상태 표, 클릭 추가 응답을 당신이 사용하고자하는 각각의 HTTP 상태 코드에 추가 할 수 있습니다.
  3. 에서 방법 당신을위한 자원 , 클릭 통합 응답
  4. 이전에 생성 한 각 HTTP 상태 코드에 대한 통합 응답추가합니다 . 입력 패스 스루 가 선택되어 있는지 확인하십시오 . 사용 람다 오류 정규식은 당신이 당신의 람다 함수에서 오류 메시지를 반환 할 때 사용되어야하는 상태 코드를 식별합니다. 예를 들면 :

    // Return An Error Message String In Your Lambda Function
    
    return context.fail('Bad Request: You submitted invalid input');
    
    // Here is what a Lambda Error Regex should look like.
    // Be sure to include the period and the asterisk so any text
    // after your regex is mapped to that specific HTTP Status Code
    
    Bad Request: .*
    
  5. API Gateway 경로는 다음을 반환해야합니다.

    HTTP Status Code: 400
    JSON Error Response: 
        {
            errorMessage: "Bad Request: You submitted invalid input"
        }
    
  6. 이 설정을 복사하여 다른 방법으로 재사용 할 수있는 방법이 없습니다. 그래서 우리는 할 일이 많은 성가신 중복 수동 입력이 있습니다!

내 통합 응답은 다음과 같습니다.

aws api gateway lambda 오류 응답 처리


사용자 지정 오류 개체를 JSON으로 반환하려면 몇 가지 문제를 해결해야합니다.

먼저 Lambda를 실패하고 문자열 화 된 JSON 객체를 전달해야합니다.

exports.handler = function(event, context) {
    var response = {
        status: 400,
        errors: [
            {
              code:   "123",
              source: "/data/attributes/first-name",
              message:  "Value is too short",
              detail: "First name must contain at least three characters."
            },
            {
              code:   "225",
              source: "/data/attributes/password",
              message: "Passwords must contain a letter, number, and punctuation character.",
              detail: "The password provided is missing a punctuation character."
            },
            {
              code:   "226",
              source: "/data/attributes/password",
              message: "Password and password confirmation do not match."
            }
        ]
    }

    context.fail(JSON.stringify(response));
};

다음으로 반환하려는 각 상태 코드에 대해 정규식 매핑을 설정합니다. 위에서 정의한 개체를 사용하면이 정규식을 400으로 설정할 수 있습니다.

. * "status": 400. *

마지막으로 Lambda에서 반환 한 errorMessage 속성에서 JSON 응답을 추출하는 매핑 템플릿을 설정합니다. 매핑 템플릿은 다음과 같습니다.

$ input.path ( '$. errorMessage')

자세한 내용과 Lambda에서 API Gateway 로의 응답 흐름을 설명하는 기사를 작성했습니다. http://kennbrodhagen.net/2016/03/09/how-to-return-a-custom-error-object -및 상태 코드-람다와 함께 API 게이트웨이에서 /


1) API Gateway 리소스 정의의 "통합 요청"화면에서 " Lambda 프록시 통합 사용" 확인란을 선택 하여 Lambda 프록시 통합 을 사용하도록 API Gateway 리소스를 구성합니다 . (또는 cloudformation / terraform / serverless / etc 구성에서 정의하십시오)

2) 두 가지 방법으로 람다 코드 변경

  • 들어오는 event(첫 번째 함수 인수)를 적절하게 처리합니다. 더 이상 베어 페이로드가 아니라 헤더, 쿼리 문자열 및 본문을 포함한 전체 HTTP 요청을 나타냅니다. 아래 샘플. 요점은 JSON 본문이 명시 적 JSON.parse(event.body)호출이 필요한 문자열이라는 것입니다 (그것을 잊지 마세요 try/catch). 예는 다음과 같습니다.
  • null를 포함한 HTTP 정보를 제공하는 응답 객체와 콜백을 호출하여 응답 statusCode, bodyheaders.
    • body문자열이어야하므로 필요 JSON.stringify(payload)에 따라 수행하십시오.
    • statusCode 숫자가 될 수 있습니다
    • headers 값에 대한 헤더 이름의 객체입니다.

프록시 통합을위한 샘플 Lambda 이벤트 인수

{
    "resource": "/example-path",
    "path": "/example-path",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "US",
        "Content-Type": "application/json",
        "Host": "exampleapiid.execute-api.us-west-2.amazonaws.com",
        "User-Agent": "insomnia/4.0.12",
        "Via": "1.1 9438b4fa578cbce283b48cf092373802.cloudfront.net (CloudFront)",
        "X-Amz-Cf-Id": "oCflC0BzaPQpTF9qVddpN_-v0X57Dnu6oXTbzObgV-uU-PKP5egkFQ==",
        "X-Forwarded-For": "73.217.16.234, 216.137.42.129",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "queryStringParameters": {
        "bar": "BarValue",
        "foo": "FooValue"
    },
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
        "accountId": "666",
        "resourceId": "xyz",
        "stage": "dev",
        "requestId": "5944789f-ce00-11e6-b2a2-dfdbdba4a4ee",
        "identity": {
            "cognitoIdentityPoolId": null,
            "accountId": null,
            "cognitoIdentityId": null,
            "caller": null,
            "apiKey": null,
            "sourceIp": "73.217.16.234",
            "accessKey": null,
            "cognitoAuthenticationType": null,
            "cognitoAuthenticationProvider": null,
            "userArn": null,
            "userAgent": "insomnia/4.0.12",
            "user": null
        },
        "resourcePath": "/example-path",
        "httpMethod": "POST",
        "apiId": "exampleapiid"
    },
    "body": "{\n  \"foo\": \"FOO\",\n  \"bar\": \"BAR\",\n  \"baz\": \"BAZ\"\n}\n",
    "isBase64Encoded": false
}

샘플 콜백 응답 형태

callback(null, {
  statusCode: 409,
  body: JSON.stringify(bodyObject),
  headers: {
    'Content-Type': 'application/json'
  }
})

참고 - 난에 방법을 생각 context등이로 context.succeed()사용되지 않습니다. 여전히 작동하는 것처럼 보이지만 더 이상 문서화되지 않습니다. 콜백 API로 코딩하는 것이 앞으로도 올바른 것이라고 생각합니다.


이 질문에 대한 모든 것을 시도했지만 (나처럼)이 작업을 수행 할 수없는 사람들은이 게시물에 대한 thedevkit 댓글을 확인하십시오 (내 하루를 저장했습니다).

https://forums.aws.amazon.com/thread.jspa?threadID=192918

전체적으로 아래에서 재현 :

나는 이것과 관련하여 문제가 있었고 개행 문자가 범인이라고 생각합니다.

foo. *는 "foo"다음에 개행 문자를 제외한 모든 문자와 일치합니다. 일반적으로이 문제는 '/ s'플래그, 즉 "foo. * / s"를 추가하여 해결되지만 Lambda 오류 정규식은이를 존중하지 않는 것 같습니다.

대안으로 다음과 같은 것을 사용할 수 있습니다 : foo (. | \ n) *


나는 Lambda의 오류가 적절한 500 오류가되기를 원했습니다. 많은 연구를 한 후 다음과 같이 작동했습니다.

LAMBDA에서

좋은 응답을 위해 다음과 같이 돌아 왔습니다.

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

    var someData1 =  {
        data: {
            httpStatusCode: 200,
            details: [
                {
                    prodId: "123",
                    prodName: "Product 1"
                },
                {
                    "more": "213",
                    "moreDetails": "Product 2"
                }
            ]
        }
    };
    return callback(null, someData1);
}

잘못된 응답의 경우 다음과 같이 반환

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

    var someError1 = {
        error: {
            httpStatusCode: 500,
            details: [
                {
                    code: "ProductNotFound",
                    message: "Product not found in Cart",
                    description: "Product should be present after checkout, but not found in Cart",
                    source: "/data/attributes/product"
                },
                {
                    code: "PasswordConfirmPasswordDoesntMatch",
                    message: "Password and password confirmation do not match.",
                    description: "Password and password confirmation must match for registration to succeed.",
                    source: "/data/attributes/password",
                }
            ]
        }
    };

    return callback(new Error(JSON.stringify(someError1)));
}

API Gateway에서

GET METHOD의 경우 / res1 / service1의 GET을 말합니다.

Through Method Response > Add Response, added 3 responses:
- 200
- 300
- 400

그때,

Through 'Integration Response' > 'Add integration response', create a Regex for 400 errors (client error):

Lambda Error Regex    .*"httpStatusCode":.*4.*

'Body Mapping Templates' > Add mapping template as:  
    Content-Type                 application/json  
    Template text box*           $input.path('$.errorMessage')  


Similarly, create a Regex for 500 errors (server error):

Lambda Error Regex    .*"httpStatusCode":.*5.*

'Body Mapping Templates' > Add mapping template as:  
    Content-Type                 application/json  
    Template text box*           $input.path('$.errorMessage')  

이제 / res1 / service1을 게시하고 위의 람다에 연결된 게시 된 URL을 누릅니다.

고급 REST 클라이언트 (또는 Postman) 크롬 플러그인을 사용하면 "httpStatusCode"에 제공된 모든 요청에 ​​대해 200 개의 http 응답 코드 대신 서버 오류 (500) 또는 400과 같은 적절한 http 코드가 표시됩니다.

API의 'Dashboard'에서 API Gateway의 다음과 같은 http 상태 코드를 볼 수 있습니다.

400 및 500 오류


The easiest way to do this is to use LAMBDA_PROXY integration. Using this method, you don't need any special transformations to be set into API Gateway pipeline.

Your return object would have to be similar to the snippet below:

module.exports.lambdaHandler = (event, context, done) => {
    // ...
    let response = {
        statusCode: 200, // or any other HTTP code
        headers: {       // optional
             "any-http-header" : "my custom header value"
        },
        body: JSON.stringify(payload) // data returned by the API Gateway endpoint
    };
    done(null, response); // always return as a success
};

It does have a few drawbacks: as having to be specially careful about error handling, and coupling your lambda function to the API Gateway endpoint; that said, if you were not really going to use it anywhere else, it is not that much of a problem.


This is how it's recommended on an AWS Compute Blog if using API Gateway. Checking to see if integration works with direct Lambda invocation.

var myErrorObj = {
    errorType : "InternalServerError",
    httpStatus : 500,
    requestId : context.awsRequestId,
    message : "An unknown error has occurred. Please try again."
}
callback(JSON.stringify(myErrorObj));

For direct Lambda invocations, this appears to be the best solution parsing on the client-side.


I'm using serverless 0.5. This is how it works, for my case

s-function.json:

{
  "name": "temp-err-test",
  "description": "Deployed",
  "runtime": "nodejs4.3",
  "handler": "path/to/handler.handler",
  "timeout": 6,
  "memorySize": 1024,
  "endpoints": [
    {
      "path": "test-error-handling",
      "method": "GET",
      "type": "AWS_PROXY",
      "responses": {
        "default": {
          "statusCode": "200"
        }
      }
    }
  ]
}

handler.js:

'use strict';
function serveRequest(event, context, cb) {
  let response = {
    statusCode: '400',
    body: JSON.stringify({ event, context }),
    headers: {
      'Content-Type': 'application/json',
    }
  };
  cb(null, response);
}
module.exports.handler = serveRequest;

참고 URL : https://stackoverflow.com/questions/31329495/is-there-a-way-to-change-the-http-status-codes-returned-by-amazon-api-gateway

반응형