API Gateway で Lambda エラーを処理する
Lambda カスタム統合の場合、統合レスポンスで Lambda によって返されたエラーを、クライアントの標準 HTTP エラーレスポンスにマップする必要があります。そうしないと、Lambda のエラーはデフォルトで 200 OK
レスポンスとして返されるため、API ユーザーは直感的に理解できません。
Lambda から返されるエラーには、標準エラーとカスタムエラーの 2 種類があります。API では、これらを異なる方法で処理する必要があります。
Lambda プロキシ統合では、Lambda は次の形式で出力を返す必要があります。
{ "isBase64Encoded" : "boolean", "statusCode": "number", "headers": { ... }, "body": "JSON string" }
この出力で、通常、statusCode
の 4XX
はクライアントエラー、5XX
はサーバーエラーです。API Gateway では、これらのエラーを処理する方法として、指定された statusCode
に従って Lambda エラーを HTTP エラーレスポンスにマッピングします。API Gateway がクライアントへのレスポンスの一部としてエラータイプ (InvalidParameterException
など) を渡すには、Lambda 関数がヘッダー ("X-Amzn-ErrorType":"InvalidParameterException"
など) を headers
プロパティに含める必要があります。
API Gateway で標準の Lambda エラーを処理する
AWS Lambda の標準エラーは次の形式になります。
{ "errorMessage": "<replaceable>string</replaceable>", "errorType": "<replaceable>string</replaceable>", "stackTrace": [ "<replaceable>string</replaceable>", ... ] }
ここで、errorMessage
はエラーの文字列式です。errorType
は、言語に依存するエラーまたは例外タイプです。stackTrace
は、エラーの発生につながったスタックトレースを示す文字列式のリストです。
たとえば、次の JavaScript (Node.js) Lambda 関数について考えてみます。
export const handler = function(event, context, callback) { callback(new Error("Malformed input ...")); };
この関数は、Malformed
input ...
をエラーメッセージとする、次の Lambda 標準エラーを返します。
{ "errorMessage": "Malformed input ...", "errorType": "Error", "stackTrace": [ "export const handler (/var/task/index.js:3:14)" ] }
同様に、次の例は同じ Exception
をエラーメッセージとし、Malformed input ...
をスローする Python Lambda 関数です。
def lambda_handler(event, context): raise Exception('Malformed input ...')
この関数は、次の Lambda 標準エラーを返します。
{ "stackTrace": [ [ "/var/task/lambda_function.py", 3, "lambda_handler", "raise Exception('Malformed input ...')" ] ], "errorType": "Exception", "errorMessage": "Malformed input ..." }
errorType
プロパティと stackTrace
プロパティの値は、言語に依存します。この標準エラーは、Error
オブジェクトの拡張または Exception
クラスのサブクラスである各エラーオブジェクトにも適用されます。
Lambda の標準エラーをメソッドレスポンスにマッピングするには、まず該当する Lambda エラーの HTTP スタータスコードを確認する必要があります。次に、その HTTP ステータスコードに関連付けられた IntegrationResponse の selectionPattern
プロパティで正規表現パターンを設定します。API Gateway コンソールの場合、この selectionPattern
は各統合レスポンスの下の [統合レスポンス] セクションに、[Lambda エラーの正規表現] として表示されます。
注記
API Gateway は、レスポンスマッピングに Java パターンスタイルの正規表現を使用します。詳細については、Oracle ドキュメントの「パターン
たとえば、新しい selectionPattern
式を設定するには、AWS CLI を使用して、次の put-integration-response コマンドを呼び出します。
aws apigateway put-integration-response --rest-api-id z0vprf0mdh --resource-id x3o5ih --http-method GET --status-code 400 --selection-pattern "Malformed.*" --region us-west-2
メソッドレスポンスで対応するエラーコード (400
) も必ず設定します。そうしないと、ランタイムに API Gateway から無効な設定エラーレスポンスがスローされます。
注記
ランタイムに、API Gateway は Lambda エラーの errorMessage
を selectionPattern
プロパティの正規表現のパターンと照合します。一致すると、API Gateway は Lambda エラーを、対応する HTTP ステータスコードの HTTP レスポンスとして返します。一致しない場合、API Gateway はエラーをデフォルトレスポンスとして返すか、デフォルトレスポンスが設定されていなければ、無効な設定例外をスローします。
特定のレスポンスで selectionPattern
の値を .*
に設定すると、このレスポンスはデフォルトのレスポンスとしてリセットされます。このような選択パターンは null (任意の未指定のエラーメッセージ) を含むすべてのエラーメッセージに一致するためです。その結果のマッピングにより、デフォルトのマッピングが上書きされます。
selectionPattern
を使用して既存の AWS CLI 値を更新するには、update-integration-response オペレーションを呼び出し、/selectionPattern
のパス値を Malformed*
パターンの指定された正規表現式に置き換えます。
API Gateway コンソールを使用して selectionPattern
式を設定するには、指定した HTTP ステータスコードの統合レスポンスを設定または更新するときに、[Lambda エラーの正規表現] テキストボックスに式を入力します。
API Gateway でカスタム Lambda エラーを処理する
AWS Lambda では、前のセクションで説明した標準エラーの代わりにカスタムエラーオブジェクトを JSON 文字列として返すことができます。エラーは、任意の有効な JSON オブジェクトです。たとえば、次の JavaScript (Node.js) Lambda 関数はカスタムエラーを返します。
export const handler = (event, context, callback) => { ... // Error caught here: var myErrorObj = { errorType : "InternalServerError", httpStatus : 500, requestId : context.awsRequestId, trace : { "function": "abc()", "line": 123, "file": "abc.js" } } callback(JSON.stringify(myErrorObj)); };
callback
を呼び出して関数を終了する前に、myErrorObj
オブジェクトを JSON 文字列に変換する必要があります。そうしないと、myErrorObj
は "[object Object]"
の文字列として返されます。API のメソッドを前の Lambda 関数と統合すると、API Gateway は以下の内容をペイロードとする統合レスポンスを受け取ります。
{ "errorMessage": "{\"errorType\":\"InternalServerError\",\"httpStatus\":500,\"requestId\":\"e5849002-39a0-11e7-a419-5bb5807c9fb2\",\"trace\":{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}}" }
通常の統合レスポンスと同様に、このエラーレスポンスはそのままメソッドレスポンスに渡すことができます。または、マッピングテンプレートを使用してペイロードを別の形式に変換することもできます。次の例は、ステータスコードが 500
のメソッドレスポンスの本文マッピングテンプレートです。
{ errorMessage: $input.path('$.errorMessage'); }
このテンプレートは、カスタムエラーの JSON 文字列が含まれている統合レスポンス本文を、次のメソッドレスポンス本文に変換します。このメソッドレスポンス本文には、カスタムエラーの JSON オブジェクトが含まれています。
{ "errorMessage" : { errorType : "InternalServerError", httpStatus : 500, requestId : context.awsRequestId, trace : { "function": "abc()", "line": 123, "file": "abc.js" } } };
API の要件によっては、カスタムエラープロパティの一部または全部をメソッドレスポンスのヘッダーパラメータとして渡す必要があります。そのためには、統合レスポンス本文からメソッドレスポンスヘッダーにカスタムエラーマッピングを適用します。
たとえば、次の OpenAPI 拡張は、errorMessage.errorType
、errorMessage.httpStatus
、errorMessage.trace.function
、および errorMessage.trace
プロパティから、それぞれ error_type
、error_status
、error_trace_function
、および error_trace
ヘッダーへのマッピングを定義します。
"x-amazon-apigateway-integration": { "responses": { "default": { "statusCode": "200", "responseParameters": { "method.response.header.error_trace_function": "integration.response.body.errorMessage.trace.function", "method.response.header.error_status": "integration.response.body.errorMessage.httpStatus", "method.response.header.error_type": "integration.response.body.errorMessage.errorType", "method.response.header.error_trace": "integration.response.body.errorMessage.trace" }, ... } } }
ランタイムに、API Gateway は integration.response.body
パラメータを逆シリアル化してヘッダーマッピングを行います。ただし、この逆シリアル化は、Lambda のカスタムエラーレスポンスの本文からヘッダーへのマッピングにのみ適用され、$input.body
を使用した本文から本文へのマッピングには適用されません。これらのカスタムエラーの本文からヘッダーへのマッピングでは、クライアントはメソッドレスポンスの一部として以下のヘッダーを受け取ります (error_status
、error_trace
、error_trace_function
、および error_type
をメソッドリクエストで宣言している場合)。
"error_status":"500", "error_trace":"{\"function\":\"abc()\",\"line\":123,\"file\":\"abc.js\"}", "error_trace_function":"abc()", "error_type":"InternalServerError"
統合レスポンス本文の errorMessage.trace
プロパティは複合プロパティです。これは JSON 文字列として error_trace
ヘッダーにマッピングされます。