API Gateway에서 Lambda를 호출할 때 event.body를 객체로 수신

소개



AWS API Gateway에서 Lambda를 호출하는 것이 자주 있다고 생각합니다.
Lambda에서는 event.body에서 요청 본문을 얻을 수 있지만,
기본적으로이 body는 문자열이므로,Content-Type:application/json 의 경우도 「JSON 캐릭터 라인」이 됩니다.
그 때문에 한번 JSON을 퍼스 해 주지 않으면 안됩니다.

예를 들어 Node.js의 경우는 이런 느낌.

index.js
exports.handler = async (event) => {
    const body = JSON.parse(event.body);
    console.log('api received!', body);

    const response = {
        statusCode: 200,
        body: JSON.stringify([body.hoge, body.fuga, body.piyo]),
    };
    return response;
};

코드측에서 JSON.parse() 하는 것 자체는 큰 수고는 아닙니다만,
귀찮은 것이 테스트입니다.

Lambda의 "테스트 이벤트 설정"에서 이런 느낌으로 쓰고 싶어요.
{
  "body": {
    "hoge": 1,
    "fuga": 2,
    "piyo": 3
  }
}

그러나 이것은 'JSON 문자열'이 아닌 'JSON 객체'이므로,
API Gateway event.body와 호환되지 않습니다.
이렇게 해야 한다. . .
{
  "body": "{\"hoge\":1,\"fuga\":2,\"piyo\":3}"
}



이거 네,,,, 힘들군요.
더블 쿼트의 이스케이프 폭풍으로, 사쿠와 필기로 쓰는 것은 무리입니다.

해결 방법



API Gateway의 매핑 템플릿이라는 기능을 사용하면,
제대로 JSON을 개체로 만든 다음 Lambda로 날 수 있습니다.

Lambda 측 트리거 설정에서 새 REST API 생성


  • 검증을 위해 매우 간단한 설정으로 API 만들기
  • 실제 운영에서 "오픈"은 위험하므로주의 사항

  • HTTP API는 매핑 템플릿을 사용할 수 없으므로 REST API로 만듭니다.



    API Gateway 리소스 설정


  • API 게이트웨이 리소스 설정으로 비행
  • ANY 메소드의 통합 요청 열기


  • Lambda에서 만든 API는 "Lambda 프록시 통합 사용"이 체크되어 있으므로 이 체크를 해제한다.
  • 체크를 해제하면 상세한 설정 항목이 나타나므로 '맵핑 템플릿'을 엽니다.

  • 매핑 템플릿 설정


  • 요청 본문 패스 스루 : "템플릿이 정의되지 않은 경우 (권장)"선택
  • 매핑 템플릿 추가 : "application/json"을 입력
  • 템플릿 생성 : "메소드 요청 패스 스루"를 선택하면 좋은 느낌의 프리셋이 들어갑니다.
  • 서식이 독특하기 때문에 처음부터 쓰는 것이 힘들지요. . 이 프리셋이 매우 고맙습니다.



  • 거의 프리셋 그대로 좋지만, body-json 는 camelCase bodyJson
  • 혹은 간단하게 body 하지만 OK

  • 편집하면 "저장"
  • 
     ##  This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
     #set($allParams = $input.params())
     {
    -"body-json" : $input.json('$'),
    +"bodyJson" : $input.json('$'),
     "params" : {
     #foreach($type in $allParams.keySet())
         #set($params = $allParams.get($type))
    

    API 배포


  • 액션에서 API 배포를 선택
  • 스테이지 'default'를 선택하고 설명을 쓰고 싶으면 쓰고 '배포'




  • Lambda의 수정 버전 및 실행 결과



    '람다 프록시 통합 사용'이 벗어나면,
    응답을 만드는 방법도 바뀝니다.statusCode 는 API Gateway 측에서 정의하므로,
    Lambda에서는 간단하게, 정상계의 리스폰스를 그대로 return 할 뿐.

    index.js
    exports.handler = async (event) => {
        const body = event.bodyJson;
        console.log('api received!', body);
    
        return [body.hoge, body.fuga, body.piyo];
    };
    

    Lambda 테스트 이벤트
    {
      "bodyJson": {
        "hoge": 1,
        "fuga": 2,
        "piyo": 3
      }
    }
    

    PC 터미널에서 curl로 API 치고 테스트
    $ curl -X POST https://example.amazonaws.com/default/mappingTemplateTest -H 'Content-Type:application/json' -d '{"hoge":1,"fuga":2,"piyo":3}'
    [1,2,3]                                                  
    

    좋은 느낌이네요!

    참고 사이트



    AWS 공식
    * REST API의 데이터 변환 설정
    * API Gateway에서 Lambda 프록시 통합 구성

    블로그 Qiita
    * [AWS] API Gateway 본문 매핑 템플릿 이해
    * API Gateway + Lambda에서 Form에서 POST 할 때 매핑 템플릿을 만들었습니다.
    * API Gateway 매핑 템플릿 설정 예

    그럼 또~.

    좋은 웹페이지 즐겨찾기