たとえば、無効なパラメーターに対して特定の400エラーを返したい場合や、ラムダ関数呼び出しの結果が201の場合に201を返します。
異なるhttpステータスコードが欲しいのですが、ラムダ関数がエラーを返していても、apiゲートウェイは常に200ステータスコードを返すようです。
たとえば、無効なパラメーターに対して特定の400エラーを返したい場合や、ラムダ関数呼び出しの結果が201の場合に201を返します。
異なるhttpステータスコードが欲しいのですが、ラムダ関数がエラーを返していても、apiゲートウェイは常に200ステータスコードを返すようです。
回答:
2016年9月9日ごとの更新
Amazonは、Lambdaプロキシ統合を使用して、これをようやく簡単にしました。これにより、Lambda関数が適切なHTTPコードとヘッダーを返すことができます。
let response = {
statusCode: '400',
body: JSON.stringify({ error: 'you messed up!' }),
headers: {
'Content-Type': 'application/json',
}
};
context.succeed(response);
APIゲートウェイでリクエスト/レスポンスのマッピングを終了します。
オプション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に設定します。
。* "ステータス":400. *
最後に、Lambdaから返されたerrorMessageプロパティからJSON応答を抽出するようにマッピングテンプレートを設定します。マッピングテンプレートは次のようになります。
$ input.path( '$。errorMessage')
私はこれについてより詳細に説明し、LambdaからAPI Gatewayへの応答フローを説明する記事をここに書き込みました:http : //kennbrodhagen.net/2016/03/09/how-to-return-a-custom-error-object -and-status-code-from-api-gateway-with-lambda /
1) API Gatewayリソース定義の[Integration Request]画面で[ Use Lambda Proxy Integration]チェックボックスをオンにして、Lambda Proxy Integrationを使用するようにAPI Gatewayリソースを構成します。(または、それをcloudformation / terraform / serverless / etc構成で定義します)
2) 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ゲートウェイ上
GETメソッドの場合は、/ 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)Chromeプラグインを使用すると、「httpStatusCode」で指定されたすべてのリクエストに対して、200 HTTP応答コードではなく、サーバーエラー(500)または400などの適切なhttpコードが表示されます。
APIの「ダッシュボード」から、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 Gatewayエンドポイントに結合する必要があるためです。とはいえ、他の場所で実際に使用しないのであれば、それほど問題にはなりません。
この質問にすべてを試してみて、これをうまく機能させることができなかった人(私のように)は、この投稿のthedevkitコメントをチェックしてください(私の一日を保存しました)。
https://forums.aws.amazon.com/thread.jspa?threadID=192918
以下で完全に再現:
私自身もこれに問題があり、改行文字が原因であると思います。
foo。*は、「foo」とそれに続く改行以外の任意の文字の出現に一致します。通常、これは「/ s」フラグ、つまり「foo。* / s」を追加することで解決されますが、Lambdaエラーの正規表現はこれを考慮していないようです。
別の方法として、foo(。| \ n)*のようなものを使用できます。
これは、API Gatewayを使用する場合にAWS Compute Blogで推奨される方法です。統合が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;