ぴよまるの雑多な技術所

間違えて休職中ってずっと書いていて心配されていました。全部ちょっとずつ齧って好きって思える技術を見つけたい。研究分野は数理最適化。

Pythonで実装したLambda + API Gatewayで任意のエラーコードを返す

サーバレスな構成を作っている時、Lambdaのステータスコードを500で返してもAPI Gatewayで200に書き換わってしまうということがありました。その時は独自エラークラスを作って、マッピングテンプレートを設定してなどなど、大掛かりなことをしたのですが、マッピングテンプレートなしで任意のエラーコードを返す方法をまとめます。

全体図

LambdaがAPI本体、API GatewayAPIのエンドポイントになる構成です。

結論

先に結論を書くと、マッピングテンプレートは必要ありません。API GatewayのPOSTの「統合リクエスト」は「Lambda プロキシ統合の使用」のまま、Lambda側でエラー用のjsonをreturnすれば大丈夫です。

参考記事 https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/handle-errors-in-lambda-integration.html

以下に具体的なコードを載せます。POSTで{'test': '何か文字列'}という値を送信するという想定です。

Lambda

import json

def lambda_handler(event, context):
    body = json.loads(event['body'])#例えばbodyを読み込んで

    if (len(body['test'])>10000):#文字が長すぎたら500エラーを返す
      return {
            'errorType': "InternalServerError",
            'httpStatus': 500,
      }
   #文字が長すぎなければ200のレスポンス
    return {
        'statusCode': 200,
        'isBase64Encoded': False,
        'body': 
            json.dumps({'result': 'OK!'})
        ,
        'headers': {
            "Content-Type" : "application/json",
            "Access-Control-Allow-Origin" : "*"
        }
    }

API Gateway

これから記事を書く予定の記事のserverless.yamlの設定をコピペすれば動きます。書いたらリンクをはります。 おそらく「OPTIONS」と「POST」の2つのリソースができていると思いますが、「OPTIONS」はpreflightレスポンスに使います。「POST」の方が実際にLambdaにリクエストを送るリソースで、細かいマッピングは「統合リクエスト」の中の「Lambda プロキシ統合の使用」にチェックをするとよしなに行ってくれるため、マッピングテンプレートが不要です。

f:id:let_piyomaru:20200310105435p:plain
API Gatewayの設定
私の環境だと「POST」の方は「メソッドレスポンス」にステータスコードを登録する必要すらありませんでした。 留意点としては、Lambda側で返すjsonの項目がAWSによって定められています。その形さえ間違わなければ動くはずです。