AWS API Gateway + lambda で任意のHTTPステータスコードを返却する
API Gateway + lambda で、任意のHTTPステータスコードを返却したい場合、次のことを行えば任意ステータスコードを返却できるようになります。
- lambda で例外を throw する
- API Gateway のIntegration Response(統合レスポンス)の設定で、lambdaのエラーメッセージとHTTPステータスコードをマッピングする
lambdaが正常終了した場合は、正規表現チェックの対象にならないようなので、lambdaは例外スローする必要があります。
lambda ファンクション作成
まずは、次のようなlambdaファンクションを作成してみます。 名前は、"test_lambda_function"としました
- パラメータに、key1 または、key2が含まれていないと例外をthrow
- key2が整数ではない場合、例外throw
# -*- coding: utf-8 -*- import json import types def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) if not "key1" in event: raise Exception("Parameter error. Missing field 'key1'.") if not "key2" in event: raise Exception("Parameter error. Missing field 'key2'.") if not type(event["key1"]) is types.UnicodeType: raise Exception("Parameter error. 'key1' is not a UnicodeType") try: # key2が整数ではない場合、例外throw return 10 + event["key2"] except Exception as e: raise Exception("Internal error. " + e.message)
API Gateway を作成する。
次のように、先ほど作成したlambdaファンクションを実行するAPI Gateway を作成します。 demoというリソースを作成し、POSTメソッドを作成しています。
API Gateway で Method Responseを設定する
Method Responseの設定画面で、HTTPステータスに400(バッドリクエスト)と500(サーバーエラー)を追加します。
API Gateway で Integration Responseの設定
Integration Responseの設定画面で、Integration Responseを追加します。 次の2つの設定を追加します。
- lambdaの例外メッセージに"Parameter error"という文字列が含まれていた場合に、400を返却
- lambdaの例外メッセージに"Internal error"という文字列が含まれていた場合に、500を返却
二つ設定が終わると、以下のようになります。
ここまでの設定で、任意ステータスコードが返却できる簡単な設定が完了しました。
テストしてみる
デプロイし動作確認してみます。
正常系
正しいJSONパラメータでHTTPのPOSTリクエストを実行し、200が返却されることを確認してみます。
$ curl -d '{"key1": "aaa", "key2": 100}' \ > -i -H "Content-type: application/json" -X POST \ > https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo HTTP/1.1 200 OK Content-Type: application/json Content-Length: 3 Connection: keep-alive ### (中略) ### 110
パラメータエラー(400)を確認
key2を設定していないリクエストを実行し400が返却されることを確認します。
$ curl -d '{"key1": "aaa"}' \ > -i -H "Content-type: application/json" -X POST \ > https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo HTTP/1.1 400 Bad Request Content-Type: application/json Content-Length: 219 ### (中略) ### {"stackTrace": [["/var/task/lambda_function.py", 13, "lambda_handler", "raise Exception(\"Parameter error. Missing field 'key2'.\")"]], "errorType": "Exception", "errorMessage": "Parameter error. Missing field 'key1'."}
インターナルサーバーエラー(500)を確認
インターナルサーバーエラーが発生するようにkey2に文字列を入力し、500が返却されることを確認します。
$ curl -d '{"key1": "aaa", "key2": "bbb"}' \ > -i -H "Content-type: application/json" -X POST \ > https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo HTTP/1.1 500 Internal Server Error Content-Type: application/json ### (中略) ### {"stackTrace": [["/var/task/lambda_function.py", 21, "lambda_handler", "raise Exception(\"Internal error. \" + e.message)"]], "errorType": "Exception", "errorMessage": "Internal error. unsupported operand type(s) for +: 'int' and 'unicode'"}
レスポンスBodyを修正する。
このままでは、レスポンスのJsonに、スタックトレースがそのまま出力され、かっこ悪いので、レスポンスを編集してみます。
API Gateway の Integration Response で Mapping Template を定義することで修正できます。
デフォルトでは、以下のパラメータがJsonレスポンスに設定されています。 * stackTrace ... スタックトレースがそのまま設定 * errorType ... Exceptionのクラス名(型) * errorMessage ... Exceptionのメッセージ
errorMessageのみ出力するように設定してみます。
デプロイし、確認してみます。
lavigne:~ mak$ curl -d '{"key1": "aaa"}' \ > -i -H "Content-type: application/json" -X POST \ > https://l43dvdh5bj.execute-api.ap-northeast-1.amazonaws.com/devel/demo HTTP/1.1 400 Bad Request Content-Type: application/json Content-Length: 62 ### (中略) ### { "errorMessage": "Parameter error. Missing field 'key2'." }