예를 들어 잘못된 매개 변수에 대해 특정 400 오류를 반환하거나 람다 함수 호출로 인해 생성이 발생했을 때 201을 반환하려는 경우.
다른 http 상태 코드를 갖고 싶지만 람다 함수가 오류를 반환하더라도 api 게이트웨이가 항상 200 상태 코드를 반환하는 것처럼 보입니다.
예를 들어 잘못된 매개 변수에 대해 특정 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와 통합합니다 .
callback
스타일을 사용하여이 작업을 수행 할 수도 있습니다 . 그냥하세요 callback(null, {statusCode: 200, body: 'whatever'})
.
return { "isBase64Encoded": True, "statusCode": 200, "headers": { }, "body": "" }
사용자 지정 HTTP 상태 코드 및 사용자 지정을 반환하는 가장 빠른 방법은 다음과 같습니다 errorMessage
.
API Gateway 대시 보드에서 다음을 수행합니다.
이전에 생성 한 각 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: .*
API Gateway 경로는 다음을 반환해야합니다.
HTTP Status Code: 400
JSON Error Response:
{
errorMessage: "Bad Request: You submitted invalid input"
}
이 설정을 복사하여 다른 방법으로 재사용 할 수있는 방법이 없습니다. 그래서 우리는 할 일이 많은 성가신 중복 수동 입력이 있습니다!
내 통합 응답은 다음과 같습니다.
return context.fail(new Error('bad one'))
사용자 지정 오류 개체를 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
). 예는 다음과 같습니다.statusCode
, body
및 headers
.
body
문자열이어야하므로 필요 JSON.stringify(payload)
에 따라 수행하십시오.statusCode
숫자가 될 수 있습니다headers
값에 대한 헤더 이름의 객체입니다.{
"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로 코딩하는 것이 앞으로도 올바른 것이라고 생각합니다.
나는 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 상태 코드를 볼 수 있습니다.
이를 수행하는 가장 쉬운 방법은 LAMBDA_PROXY 통합 을 사용하는 것 입니다. 이 방법을 사용하면 API Gateway 파이프 라인으로 설정하는 데 특별한 변환이 필요하지 않습니다.
반환 객체는 아래 스 니펫과 유사해야합니다.
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
};
여기에는 몇 가지 단점이 있습니다. 오류 처리에 대해 특별히주의해야하고 람다 함수를 API 게이트웨이 엔드 포인트에 연결해야한다는 점입니다. 즉, 다른 곳에서 실제로 사용하지 않을 경우 그다지 문제가되지 않습니다.
이 질문에 대한 모든 것을 시도했지만 (나처럼)이 작업을 수행 할 수없는 사람들은이 게시물에 대한 thedevkit 주석을 확인하십시오 (내 하루를 저장했습니다).
https://forums.aws.amazon.com/thread.jspa?threadID=192918
전체적으로 아래에서 재현 :
나는 이것과 관련하여 문제가 있었고 개행 문자가 범인이라고 생각합니다.
foo. *는 "foo"다음에 개행 문자를 제외한 모든 문자와 일치합니다. 일반적으로이 문제는 '/ s'플래그, 즉 "foo. * / s"를 추가하여 해결되지만 Lambda 오류 정규식은이를 존중하지 않는 것 같습니다.
대안으로 다음과 같은 것을 사용할 수 있습니다 : foo (. | \ n) *
이것이 API Gateway를 사용하는 경우 AWS 컴퓨팅 블로그에서 권장되는 방법입니다. 통합이 직접 Lambda 호출과 함께 작동하는지 확인합니다.
var myErrorObj = {
errorType : "InternalServerError",
httpStatus : 500,
requestId : context.awsRequestId,
message : "An unknown error has occurred. Please try again."
}
callback(JSON.stringify(myErrorObj));
직접 Lambda 호출의 경우 이는 클라이언트 측에서 구문 분석하는 최상의 솔루션 인 것으로 보입니다.
서버리스 0.5를 사용하고 있습니다. 이것이 제 경우에 작동하는 방식입니다.
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;