HttpServletRequest body 여러번 읽기

fart man·2026년 1월 27일

과제의 일부로 HttpServletRequest와 HttpServletResponse의 body를 log로 남겨야 하는 상황이 왔다.

그 까지꺼 걍 getBody같은 method가 있겠지뭐~ 하고 ctrl-space를 눌러 봤지만... 없다.

알고 보니 HttpServletRequest와 HttpServletResponse둘다 memory를 아끼기 위해 stream을 중점적으로 사용하도록 설계되어있다.

request.getReader는 한번 읽고 나면 다시 읽을 수 없다.
response는 아예 쓰기만 가능 할 뿐 읽을 수는 없다.

그렇기 때문에 각각

ContentCachingRequestWrapper와 ContentCachingResponseWrapper로 감싸 주어야 한다.

산넘어 산, ContentCachingRequestWrapper의 이상한점

뭔가 ContentCachingRequestWrapper는 getReader를 부를 때 마다 새로운 stream객체를 생성할 거 같지만 소스코드를 까보면 그렇지 않다.

	@Override
	public BufferedReader getReader() throws IOException {
		if (this.reader == null) {
			this.reader = new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
		}
		return this.reader;
	}

보면 알 수 있듯이 getReader는 처음에 만든 stream을 재사용 하는 것을 알 수 있다.

그리고 getReader의 stream도 한번 읽은 이후에는 재사용이 불가능 하므로 여러번 반복해서 읽고 싶다면 getContentAsByteArray를 이용해야한다.

문제는 getContentAsByteArray는 getReader로 한번 읽은 후에야 정상 작동 한다는 점이다... (왜이리 불친절하게 만들었을까....)

결국 가장좋은 해결책은 HttpServletRequestWrapper를 상속받은 나만의 wrapper를 만드는 거겠지만... 나중에.

산넘어 산넘어 산, ContentCachingResponseWrapper의 이상한점

정말 불편하게도 ContentCachingResponseWrapper이상한게 있다.

자신이 cache한 body의 내용을 copyBodyToResponse을 호출 하지 않는 이상 실제로 네트워크에 쓰지 않는다.

근데 무섭다고 여러번 부를 수도 없고 딱 한번만 불러야 한다....

0개의 댓글