API Gateway에서 Lambda 오류 처리

19037 단어 APIGateway람다AWS
소재로 하는 아키텍처



API Gateway의 반환 값을 형식화합니다.



에러시에 400/500대의 스테이터스 코드를 붙여 Description를 붙여 돌려주고 싶다.

1 Exception 클래스를 상속하고 확장한 예외 클래스를 만듭니다.
2 에러시에 raise한다.

Lambda(1)
import json
import boto3
import logging
import traceback

logger = logging.getLogger()
logger.setLevel(logging.INFO)

dynamodb = boto3.resource('dynamodb')

# 例外クラスを拡張
class ExtendException(Exception):
    def __init__(self, statusCode, description):
        self.statusCode = statusCode
        self.description = description

    def __str__(self):
        obj = {
            "statusCode": self.statusCode,
            "description": self.description
        }
        return json.dumps(obj)

def lambda_handler(event, context):

    # validation check
    if not "key" in event or not isinstance(event["key"], int):
        raise ExtendException(400, "Bad Request")

    # 何らかの処理

    return 0

테스트

response
{
  "errorMessage": "{\"statusCode\": 400, \"description\": \"Bad Request\"}",
  "errorType": "ExtendException",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 29, in lambda_handler\n    raise ExtendException(400, \"Bad Request\")\n"
  ]
}

3 API Gateway 응답 매핑




Lambda 오류의 정규식은 .*statusCode: 400,.*를 지정합니다.
Lambda에서 반환된 오류 응답의 errorMessage 부분만 반환합니다.

테스트

response
{
  "statusCode": 400,
  "description": "Bad Request"
}

다른 Lambda로부터 호출했을 때에 에러 내용을 표시한다.



다음과 같이 오류 응답을 선택할 수 있습니다.
try:
    pass
except urllib.error.HTTPError as err:
    res = err.read().decode("utf-8")

Lambda(2)
import json
import urllib.request, urllib.error
import logging
import traceback

logger = logging.getLogger()
logger.setLevel(logging.INFO)

class ExtendException(Exception):
    def __init__(self, statusCode, description):
        self.statusCode = statusCode
        self.description = description

    def __str__(self):
        obj = {
            "statusCode": self.statusCode,
            "description": self.description
        }
        return json.dumps(obj)

request_url = "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1"
api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

def lambda_handler(event, context):
    try:
        headers = {'x-api-key': api_key, "Content-Type":"application/json"}
        method = "POST"

        # validation errorするようにAPIをコールする。
        request_json = {
            "notExistKey": 1
        }

        req = urllib.request.Request(url=request_url, method=method, headers=headers, data=json.dumps(request_json).encode())

        with urllib.request.urlopen(req) as res:
            body = res.read().decode("utf-8")

    except urllib.error.HTTPError as err:
        traceback.print_exc()
        res = err.read().decode("utf-8")
        res = json.loads(res)
        logger.info("------------------")
        logger.info(res)
        logger.info("------------------")
        raise ExtendException(500, "[ERROR] {} : {}".format(res["statusCode"], res["description"]))

    except urllib.error.URLError as err:
        traceback.print_exc()
        res = err.read().decode("utf-8")
        res = json.loads(res)
        logger.info("------------------")
        logger.info(res)
        logger.info("------------------")
        raise ExtendException(500, "[ERROR] {} : {}".format(res["statusCode"], res["description"]))
    except:
        traceback.print_exc()
        raise ExtendException(500, "Internal Error")

    return json.loads(body)

테스트

response
{
  "errorMessage": "{\"statusCode\": 500, \"description\": \"[ERROR] 400 : Bad Request\"}",
  "errorType": "ExtendException",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 45, in lambda_handler\n    raise ExtendException(500, \"[ERROR] {} : {}\".format(res[\"statusCode\"], res[\"description\"]))\n"
  ]
}


추가 2020/08/06

Lambda 타임아웃을 처리합니다.



상기의 설정에서는 Lambda(1)로 타임 아웃 했을 때에 스테이터스 코드 200이 돌려 버린다.
{
  "errorMessage": "2020-08-06T13:36:57.311Z 312a1819-af1a-4fc5-bb9c-f8ed8f573a9b Task timed out after 3.00 seconds"
}

통합 응답의 정규 표현에서는 이하와 같이 지정하는 것으로 Lambda의 타임 아웃을 핸들링할 수 있다.
.*"statusCode": 500,.*|.*Task timed out after.*

좋은 웹페이지 즐겨찾기