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 대시 보드에서 다음을 수행합니다.
- 에서 방법 당신을위한 자원 , 클릭 방법 응답
- 에서 HTTP 상태 표, 클릭 추가 응답을 당신이 사용하고자하는 각각의 HTTP 상태 코드에 추가 할 수 있습니다.
- 에서 방법 당신을위한 자원 , 클릭 통합 응답
이전에 생성 한 각 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" }
이 설정을 복사하여 다른 방법으로 재사용 할 수있는 방법이 없습니다. 그래서 우리는 할 일이 많은 성가신 중복 수동 입력이 있습니다!
내 통합 응답은 다음과 같습니다.
사용자 지정 오류 개체를 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
,body
및headers
.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 상태 코드를 볼 수 있습니다.
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;
'Programing' 카테고리의 다른 글
Vim에서 현재 파일의 경로를 영구적으로 표시하려면 어떻게해야합니까? (0) | 2020.09.13 |
---|---|
Eclipse Git 플러그인에서 기본 작성자 및 커미터를 어떻게 변경합니까? (0) | 2020.09.13 |
Google API 클라이언트로 토큰을 새로 고치는 방법은 무엇입니까? (0) | 2020.09.13 |
GitHub : "wip"브랜치 란 무엇입니까? (0) | 2020.09.13 |
단일 SQL에 여러 "WITH AS"를 사용할 수 있습니까?-Oracle SQL (0) | 2020.09.13 |