Connection을 닫는 400 응답??
여러분의 서버에서 400응답을 반환하면 어떤 일이 발생하는지 알고 계신가요??
tomcat에서는 400 응답을 반환하면 커넥션이 닫힙니다. http/1.1에서는 keep-alive 때문에 커넥션을 유지해야 하지만, 몇몇 상태 코드에서는 커넥션이 닫힐 수 있습니다.
코드로 확인
spring boot에서 @RequestParma의 값을 잘못 넣어주면 400 응답을 받을 수 있습니다.
1 |
|
아래 스크린샷을 보면 400응답에서 실제로 커넥션이 닫히는 것을 확인 할 수 있습니다.
왜 그런지 찾아보기 위해서 tomcat 소스코드에서 Http11Processor.java를 살펴보았습니다.
1 | /** |
코드를 보니 400, 408, 411, 413, 414, 500, 501, 503 응답을 보내면 연결을 닫는다고 합니다.
근거는 무엇일까요??
왜 저 상태코드에서 커넥션을 닫는 것일까요? 근거를 찾기 위해서 상태 코드에 대해 명세한 RFC 7231 6.5절을 찾아봤습니다.
6.5.1. 400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).
6.5.11. 413 Payload Too Large
The 413 (Payload Too Large) status code indicates that the server is
refusing to process a request because the request payload is larger
than the server is willing or able to process. The server MAY close
the connection to prevent the client from continuing the request.
하지만 아직 의아한 부분이 있습니다. 413처럼 커넥션을 닫을 수 있다고 명시하는 상태코드가 있는 반면에 400처럼 명시하지 않는 상태코드도 있기 때문입니다.
추가로 RFC 7230을 찾아보았습니다. RFC 7230 6.3절에 영속 연결(persistent connection)에 대한 설명 중 일부입니다.
A server MUST read the entire request message body or close the connection after sending its response, since otherwise the remaining data on a persistent connection would be misinterpreted as the next request.
위 내용을 해석해 보면 요청 메시지 본문 전체를 읽을 수 없는 상황에서는 커넥션을 닫아야 한다고 합니다. 왜냐하면 커넥션을 닫지 않으면 다음 요청으로 잘못 해석될 수 있기 때문입니다.(tcp는 stream 기반이기 때문)
마침 tomcat 소스코드에서 확인한 커넥션을 닫는 응답 코드들은 다음 요청에 영향을 줄 수 있는 상태 코드인 것을 알 수 있습니다.
결론
평소에 무심코 사용하던 400 응답이 커넥션을 닫고 있었다는 사실을 알게 되었습니다. 이런일이 또 발생하지 않도록 사용하는 기술에 대해 더 관심을 가지는 계기가 됐습니다.