이미 일년도 넘은 내용이지만 에버노트에서 꺼내보면서 이것 저것 정리도 해볼겸 RequestBody의 내용을 로그로 남기고 싶다. 에 이어서 좀 더 관련 내용을 적어보았다. filter 를 이용해서 request body 를 로그로 찍어보자.
우선 문자열과 input stream 의 편리한 처리를 위해서 다음과 같이 의존성을 추가한 다음에 진행하였다.1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
테스트를 위해서 다음과 같이 간단하게 post 방식의 api를 하나 생성하고, Parameter 클래스를 정의했다.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class Parameter {
private String message;
public void setMessage(String message) {
this.message = message;
}
}
@RestController
public class TestController {
@PostMapping("/test")
public Boolean postTest(@RequestBody Parameter body) {
return Boolean.TRUE;
}
}
Filter 인터페이스를 구현하여 ReadableRequestWrapperFilter 클래스를 만들어주었다. ReadableRequestWrapper 에서 요청에 대한 내용들을 읽어서 출력해볼 것이다.
1 | public class ReadableRequestWrapperFilter implements Filter { |
HttpServletRequestWrapper 을 상속받은 ReadableRequestWrapper 클래스를 다음과 같이 만들었다.1
2
3
4
5
6
7
8
9
10
11
12public class ReadableRequestWrapper extends HttpServletRequestWrapper{
public ReadableRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
try {
InputStream is = request.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
System.out.println("----- input " + bufferedReader.lines().collect(Collectors.joining(System.lineSeparator())));
} catch (Exception e) {
throw e;
}
}
}
http request에서 input stream을 읽어 들인 다음, 해당 내용을 출력하도록 했다. ----- input {"message":"test"}
와 같이 결과가 출력된다.
1 | 2018-10-23 07:08:06.635 WARN 7936 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public java.lang.Boolean com.daeuky.springboot.mybootapp.TestController.postTest(com.daeuky.springboot.mybootapp.Parameter) |
그러나 위의 메시지에서 확인 할 수 있듯이 request body가 사라져서 @RequestBody 로 선언해준 Parameter 객체가 생성되지 않는다. 기본적으로 스트림은 한 번 읽는게 원칙이다.
ReadableRequestWrapper 클래스에 버퍼 byte[] rawData
를 정의한 다음 input stream 을 읽어 스트림을 byte[] 타입으로 버퍼에 저장했다. getInputStream() 을 오버라이딩 하여 input stream 읽기 요청이 들어오는 경우, 버퍼에 저장해둔 내용을 반환해준다. getReader() 메소드를 오버라이딩하여 버퍼의 내용을 BufferedReader 타입으로 반환한다.
1 | public class ReadableRequestWrapper extends HttpServletRequestWrapper { |
테스트를 위해서 curl 을 날려보았다.1
$ curl -XPOST -H "Content-Type: application/json" -d '{"message":"test"}' http://localhost:8080/test
최초에 확인했던 로그 ----- input {"message":"test"}
가 정상적으로 노출되고, controller에도 정상적으로 파라미터가 전달되어 Parameter 객체에서도 내용을 확인 할 수 있다.
Comments