@PutMapping / @DeleteMapping : @RequestParam 사용하기

PutMapping / DeleteMapping : Body 읽기

  • @PutMapping이나 @DeleteMapping을 통해 리소스 id를 @PathVariable로 받고 그 외의 변수들은 @RequestParam으로 받으려고 했을 때, query string이 아닌 body에 데이터를 넣고 전송하려하면 정상적으로 작동하지 않는다.

  • body에 담긴 데이터가 POST Method에서는 @RequestParam에는 매핑이 되는데 왜 PUT, DELETE는 안되나 싶어서 찾아봤다.


해결 방법 1

  • 이슈되는 부분은 spring이 아닌 tomcat에 있었다. tomcat에서 request의 body 내용을 HTTP POST Method 일 때만 파싱해오도록 설정되어 있기 때문이다. 참고 [1]

  • 이를 해결하기 위한 한가지 방법으로 HTTP DELETE / PUT Method 일 경우에도 request의 body 내용을 파싱하도록 설정하는 것이다.

  • 그 설정은 tomcat의 server.xml에서 parseBodyMethods=“POST, DELETE” 이런 식으로 설정해 주는 것이다. 참고 [2]


  • 이 설정이 어떻게 실행되는지 톰캣 라이브러리를 보면 다음과 같다. 참고 [3]

    • Connector.java

      • 아래 그림을 보면 parseBodyMethods의 디폴트 값이 POST이라서, HTTP POST Method일 때는 별다른 설정없이 body 내용을 잘 가져올 수 있다.

      • parseBodyMethods의 getter, setter를 미루어보아, server.xml에서 설정한 문자열을 그대로 저장할 뿐만아니라 여러 개일 경우 ','로 잘라서 hashset 형태로 저장해놓는 것을 볼 수 있다.

    • Request.java

      • 이번에는 실제로 request가 들어오면 parseBodyMethods로 설정한 HTTP Method에 있는지 비교하는 부분이다.

해결 방법 2

  • 또 다른 방법으로는 스프링에서 제공하는 필터가 있었습니다.

  • request가 들어오면 서블릿에 가기전에 springframework.web.filter.HttpPutFormContentFilter 를 통해 필터단에서 request.getMethod()가 PUT / PATCH Method이고 미디어 타입이 application/x-www-form-urlencode 인 경우에 body를 파싱을 하는 것이다. 참고 [4]

  • HttpDeleteFormContentFilter는 없지만, 위의 코드를보아 HttpPutFormContentFilter에 DELETE 검사만 추가하여 똑같이 커스텀 필터를 만들어 사용할 수 있을 것 같다.

댓글