ハマった時は # init 0

試したことを書き綴ってます

AWS API Gateway + lambda で任意のHTTPステータスコードを返却する

API Gateway + 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メソッドを作成しています。

f:id:init0:20161127233012p:plain

API Gateway で Method Responseを設定する

Method Responseの設定画面で、HTTPステータスに400(バッドリクエスト)と500(サーバーエラー)を追加します。

f:id:init0:20161127234317p:plain

API Gateway で Integration Responseの設定

Integration Responseの設定画面で、Integration Responseを追加します。 次の2つの設定を追加します。

  • lambdaの例外メッセージに"Parameter error"という文字列が含まれていた場合に、400を返却
  • lambdaの例外メッセージに"Internal error"という文字列が含まれていた場合に、500を返却

f:id:init0:20161127235143p:plain

二つ設定が終わると、以下のようになります。

f:id:init0:20161127235334p:plain

ここまでの設定で、任意ステータスコードが返却できる簡単な設定が完了しました。

テストしてみる

デプロイし動作確認してみます。

f:id:init0:20161128003428p:plain f:id:init0:20161128003410p:plain

正常系

正しい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のみ出力するように設定してみます。

f:id:init0:20161128010745p:plain

デプロイし、確認してみます。

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'."
}