JWT 예외 처리를 하는 과정에서 에러 리스폰스가 제대로 전달이 되었지만, response의 status가 계속 200으로 설정되어 있는 것을 목격
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
Map<String, Object> body = new HashMap<>();
body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
body.put("error", "Unauthorized");
body.put("message", exception.getMessage());
body.put("path", request.getServletPath());
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
분명 setStatus를 설정하였다.. 그런데 왜 200 OK가 뜰까?
setStatus를 하는 과정을 따라가 보았다.
@Override
public void setStatus(int sc) {
checkFacade();
if (isCommitted()) {
return;
}
response.setStatus(sc);
}
우선 checkFacade()
로 해당 response가 null인지 체크한다.
isCommitted()
의 경우 isAppCommitted()
라는 메서드가 또 있었다.
/**
* Application commit flag accessor.
*
* @return <code>true</code> if the application has committed the response
*/
public boolean isAppCommitted() {
return this.appCommitted || isCommitted() || isSuspended() ||
((getContentLength() > 0) && (getContentWritten() >= getContentLength()));
}
함수를 설명하는 주석을 번역해보니 애플리케이션 커밋 플래그 접근자. 응용 프로그램이 응답을 커밋한 경우 true
라고 한다.
어디서 true가 생기는 것일까를 보는 도중
coyoteResponse의 isCommited()
값이 true였다.
/**
* Has the output of this response already been committed?
*
* @return <code>true</code> if the response has been committed
*/
@Override
public boolean isCommitted() {
return getCoyoteResponse().isCommitted();
}
그래서 setStatus는 이미 commited된 상태이므로 status를 설정하지 않고 return 되는 것이었다.
그래서 commited가 어느 부분에서 true로 변경되는지 찾아보게 되었고, writeValue 메서드를 사용하는 순간에 commited가 true로 변경되는 것을 알게 되었다.
writeValue 메서드를 열심히 타고들어가다보니 Http11Processor 클래스의 prepareResponse 메서드 마지막에 있는 outputBuufe.commit() 메서드가 response를 commited로 변경하는 것을 발견하였다.
writeValue()
는 response의 committed 필드를 true로 바꾼다.setStatus()
는 isAppCommitted
가 false값을 가져야 한다.