Network

HTTP The Definitive Guide - 03. HTTP Messages

깡구_ 2022. 11. 4. 12:05

title: HTTP The Definitive Guide - 03. HTTP Messages
date: 2022-11-04
tags:

  • Network
  • HTTP



Introduction

HTTP The Definitive Guide




GDSC에서 해당 서적을 통해 HTTP를 공부하는 스터디에 참가하고 있다.
HTTP 이전의 내용은 개인적으로 공부하며 채울 예정이다.
이번 Chapter는 03장 HTTP Messages 이다.


Purpose

HTTP를 이용할 때 전달이 되는 Message 자체에 대해 파악한다.


The Flow of Message

HTTP Message는 HTTP Application끼리 데이터를 전송할 때 사용하는 하나의 블록이다.
Client에서 Server로 흘러갈 때는 Inbound 라고 하며, Server에서 Clinet로 흘러갈 때는 Outbound라고 한다.
또한 UpstreamDownstream 개념이 존재한다. Client -> Server의 Request일 때는 Client가 Upstream, Server가 Downstream이다.
Server -> Client의 Response일 때는 반대로 Server가 Upstream, Client가 Downstream이다.
위 개념을 통해 HTTP Message는 항상 Downstream으로 향하는 것을 직관적으로 알 수 있다.
다만, 당연하게도 전송을 하는 측이 Upstream, 수신을 하는 측이 Downstream일텐데, 이를 용어까지 도입하여 개념을 잡은 이유는 이해가 되지 않는다.


The Parts of a Message

HTTP Message는 Message에 대한 간략한 정보가 포함된 Start Line, Message에 대한 Attribute가 들어있는 Header, 데이터를 포함할 수 있는 Body로 구분된다.
Start Line와 Header는 ASCII Text이며 Line별로 구분이 되며, 각 Line의 구분은 Carriage Return (ASCII 13)과 Line Feed (ASCII 10)을 조합한 CRLF로 구분이 된다.
옛날에 사용하던 HTTP Application의 경우 CRLF가 아닌 CR, 혹은 LF만 사용하기도 한다.
Header Attribute에 값이 입력될 때 CRLF로 인하여 문제가 발생하는 HTTP Response Splitting이 존재한다.
이러한 취약점이 존재하며, 입력값에 CRLF가 있는지 확인한 후 치환 작업을 진행하여 문제를 해결할 수 있다.
Body의 경우 Text 혹은 Binary 형식의 데이터로 존재하며, 필수가 아니기에 비어있을 수도 있다.

CRLF varies from System

시스템별로 사용하는 Default 방식이 다르다. Windows의 경우 CRLF, Unix/Linux는 LF, 구형 Mac은 CR을 사용한다. OSX 이상의 Mac에서는 CRLF 혹은 LF를 사용한다고 하는데, 더 찾아봐야 할 것 같다.
이처럼 시스템에 따라 CRLF가 다르기에 Git과 같은 협업 도구를 이용할 때 문제가 발생하기도 한다.

Message Configuration

HTTP Message Configuration

HTTP Message는 Request와 Reponse로 나뉘며, 위와 같은 구조를 띈다.

  • method - HTTP Method로, Chapter 04에서 자세히 다룬다.
  • request-URL - Server의 URL이다.
  • version - HTTP Version을 명시한다. Version에 따라 지원하는 기술이 다르기에 이를 명시해주어야 한다. a.b 방식이며 2.22와 2.3이 존재할 경우 숫자가 더 큰 22를 가진 2.22가 최신 Version이다.
  • status-code - HTTP Response와 함께 수행 결과를 간단한 숫자로 알려준다. 해당 Chapter의 뒤에서 더 자세히 다룬다.
  • reason-phrase - Status Code를 인간이 이해하기 쉽도록 적어놓는 구문이나 생략해도 된다. 동일한 Status Code에서 서로 다른 reason-phrase가 전달 되더라도 Status Code는 공식적으로 규정되어 있기에 Status Code를 우선적으로 처리하면 된다.
  • headers - Header 내부에는 Attribute가 없을 수도 있다. Json, Python의 Dictionary와 같이 Key : Value 형태이다. Attribute들의 끝에 CRLF가 들어가 구분하게 되며, 마지막 한 줄은 CRLF만 존재하여 Header의 끝을 알릴 수도 있다. 자세한 Header 또한 해당 Chapter의 뒤에서 더 자세히 다룬다.
  • entity-body - 데이터가 해당 부분에 존재할 수 있다. 필수가 아니기에 비어있을 수 있으며, 동일하게 CRLF를 이용하여 Body의 끝을 알린다. Body에 대해서는 Chapter 15에서 자세히 다룬다.

Body에서도 CRLF를 명시해야 하지만, 이를 생략하는 경우도 많이 존재하기에 Body가 생략되더라도 이를 인지할 수 있어야 한다.

Start Line

모든 HTTP Message는 Start Line으로 시작한다. 각 Field는 공백으로 구분되어 있다.
Request의 경우 어떤 동작을 해야 하는지 적혀있으며, Response는 동작의 결과를 알려준다.

Body

Body는 선택적으로 사용하나, 과거에는 Body만 존재할 때도 있었다.
HTTP 0.9의 경우, Method와 URL만 가지는 Request를 보내고 Response로 Body만 보낼 수 있었다.
너무 제한적인 동작만 수행할 수 있기에 개선된 방식이 사용되었다.

Method

HTTP 1.1부터 Server는 GET과 HEAD Method는 필수적으로 구현해야 한다.
또한 구현된 Method는 유저의 권한에 따라 사용이 불가능할 수도 있다. 모든 유저가 모든 Method를 사용할 수 있는 것은 아니다.

HTTP Method는 현재 40가지이며, 그 중 주로 사용되는 Method는 9가지이다.
이 중 GET과 HEAD와 같은 Method는 Server의 무언가를 바꾸지 않는 안전한 Method이다.

  • GET - 가장 일반적으로 사용하는 Method로, Server의 특정 정보를 가져올 때 사용한다. HTTP 1.1부터는 Server에 필수적으로 구현이 되어 있어야 한다.
  • HEAD - GET Method와 매우 유사하나, GET Method는 Body가 존재할 수도 있으나 HEAD Method는 Header만 요구한다. 실제 Resource에 접근하지 않고 Resource에 대한 다양한 정보를 확인할 수 있다. HEAD 또한 HTTP 1.1부터 Server에 필수적으로 구현이 되어 있어야 한다.
  • POST - 새로운 데이터를 Server에 생성한다. 동일한 데이터가 존재하더라도 중복하여 생성하기에 멱등하지 않다.
  • PUT - 새로운 데이터를 생성하거나 기존의 데이터를 수정한다. POST와 동작이 매우 유사하나, 동일한 작업을 여러번 보내더라도 한 번만 실행한 것과 동일하게 동작하기에 멱등하다.
  • PATCH - Resource의 일부를 수정한다. PUT은 전체 Resource를 교체해야 하였으나, PATCH는 부분 수정이 허용된다. PUT과는 다르게 멱등하지 않다.
  • DELETE - 특정 Resource를 삭제한다. 권한이 올바르지 않다면 DELETE가 수행되지 않으며, 유저는 DELETE를 수행하겠다는 것은 알아도 DELETE가 올바르게 완료되는 것은 알 수 없다.
  • OPTIONS - Server가 모든 Resource 혹은 특정 Resource에 대해 지원하는 Method를 확인할 때 사용한다. 다만 Caching 문제가 있어 사용하지 않는 것이 좋다는 의견이 많으며, 유저의 권한에 맞는 Method를 알려주는지에 대해서는 찾아볼 수 없었다.
  • CONNECT - Server와 Connection을 맺을 때 사용한다.
  • TRACE - Request와 Response 과정에서의 Network 흐름을 확인할 수 있다. Request를 보낸 이후 Response를 받기까지 여러 방화벽, Proxy, Gateway 등을 거치며, 이러한 것들이 모두 기록된다. 의도한대로 Network를 거치는지 확인하거나 Proxy 혹은 다른 App이 Request에 미치는 영향을 확인할 때 사용한다. 추가적으로 TRACE는 진단의 성격을 띄기에 일반적인 Method와는 다르며, 이러한 Method를 구분할 수 없다. Body가 존재하지 않는다.

이 외에도 많은 Method가 존재하며, Server에 따라 구현이 되지 않아 사용이 불가능할 수도 있다.
또한 정식 Method가 아니더라도 내부적으로 편하게 사용하기 위하여 고유의 Method를 구현하여 사용하는 경우도 있다고 한다.
이렇게 추가적으로 구현한 Method는 Extension Method라고 불린다.
Extension Method를 사용한다면 통신을 중계해주는 Proxy와 같은 것들은 Method를 이해하지 못 하지만, 문제가 없다면 우선 Downstream으로 전달을 시도할 것이다.
이를 이용할 때는 Be conservative in what you send, be liberal in what you accept 라는 규칙을 따르는 것이 가장 좋다고 한다.

Status Code

Status Code는 HTTP Request의 결과를 알려준다. reason-phrase는 인간이 이해하기 쉽게 되어 있으며, Status Code는 프로그램이 이해하기 쉽게 숫자로 되어 있다.
공식적으로 명시되지 않은 Status Code의 경우 내부적으로 사용하기 위한 Extension이다.
Status Code는 세자리 양의 정수이며, 백의 자리별로 Group을 나눈다.

1xx는 Informational Status Code이다.

  • 100 Continue - Server가 Body를 받아들일 수 있는지 미리 확인한 후, Body를 전송한다. Server는 준비가 되었다면 100을 보내며, 100을 보내기 전에 Body가 수신될 경우 100은 보내지 않아도 된다. HTTP 1.1 이상에서만 사용 가능하며, 그 이전 Version이거나 Version 명시가 안 되어있을 경우 417로 Response한다.
  • 101 Switching Protocol - Server가 Upgrade Header에 명시된 다른 Protocol로 바꾼 것을 의미한다.

 

2xx는 Success Status Code이다.

  • 200 OK - Request가 올바르다는 것을 알려준다. Response Body에 Request Resource가 들어있다.
  • 201 Created - POST, PUT과 같은 Request가 올바르게 처리되었다는 것을 알려준다.
  • 204 No Content - Response에 Body가 없다는 의미이다. DELETE와 같이 Response할 Resource가 없을 때 사용하며, GET을 이용 시 Resource가 없다면 200과 함께 빈 Body를 Response한다.

 

3xx는 Redirection Status Code이다.

  • 301 Moved Permanentely - Request에 사용한 URL이 영구적으로 바뀌었다는 의미이다.
  • 302 Found - Request에 사용한 URL이 임시로 바뀌었다는 의미이다. 303과 307과 유사하나 302가 먼저 정의되었으며, 사용한 Method를 Redirection시에도 이용해야 하지만 대부분의 Browser는 이를 무시하고 GET Method를 사용하였다.
  • 303 See Other - 302와 유사하며, PUT과 POST Request를 GET Resource로 Redirection하기 위해 사용한다.
  • 304 Not Modified - 조건이 포함된 Request를 보낼 때, 조건이 True가 아닐 때 발생한다.
  • 307 Temporary Redirect - 302와 유사하며, 처음 Request에 사용한 Method가 Redirection시 유지된다.
    현재 Browser는 Redirection시 항상 GET으로 수행되며, 302, 303, 307을 올바르게 구현하지 않는 Browser 혹은 Server도 존재한다.

 

4xx는 Client Error Status Code이다.

  • 401 Unauthorized - 유저에 대한 인증이 필요하다는 것을 의미한다.
  • 403 Forbidden - Request가 Server에 의해 거절되었다는 것을 의미한다. Body에 거절 이유를 명시할 수 있으나, 이를 알리지 않기 위하여 사용하는 경우가 많다.
  • 404 Not Found - Request에 사용한 URL을 찾을 수 없다는 것을 의미한다.
  • 405 Method Not Allowed - Request한 URL에 해당 Method를 사용할 수 없다는 것을 의미한다. Response로 해당 Resource에 허용되는 Method를 알려준다.
  • 408 Request Timeout - Server가 일정 시간 이내에 완전한 Request를 받지 못한 것을 의미한다. 이 시간은 Server마다 다르지만 일반적으로 어떠한 올바른 Request가 들어와도 처리 가능한 시간이 주어진다.

 

5xx는 Server Error Status Code이다.

  • 500 Internal Server Error - 예측하지 못한 Error 혹은 다른 5xx Status Code를 사용하기 애매할 때 사용된다. 원인은 너무나도 다양하다.
  • 502 Bad Gateway - Upstream Server로부터 잘못된 Response를 받았음을 의미한다.
  • 503 Service Unavailable - Server가 요청한 Resource를 현재는 Service를 할 수 없음을 의미한다. 언제 해당 Resource를 사용가능한지 안다면 Body에 해당 정보를 넣어서 알려줄 수도 있다.
  • 504 Gateway Timeout - 408과 유사하며, Upsteram Server로부터 일정 시간 이내에 Response를 받지 못하였음을 의미한다.

 

자주 사용되는 Status Code에 대해서만 적었으며, 이 외에도 매우 다양한 Status Code가 존재한다.

Header

HTTP Header는 위에서 언급하였듯이 HTTP Method의 Attribute를 나타내며, 없을 수도 있다.
Key : Value 형태로 Attribute를 나열한다.

Header Classification

Header는 아래와 같이 분류할 수 있다.

  • General Header - Request와 Response 모두에 나타날 수 있다. Caching과 관련된 Header도 존재한다.
    • Via - 해당 Message가 도착하기까지 거친 Proxy 혹은 Gateway를 보여준다.
  • Request Headers - Response에 대한 정의, 조건, 보안, Proxy의 성능을 위한 정보 등을 포함한 Request에 대한 상세한 정보를 제공한다.
    • Host - Request를 하는 Client의 Host 이름과 Port이다.
    • Referer - 현재 Request에 사용하는 URL을 알려준 문서의 URL이다.
    • User-Agent - Request를 하는 Client Application의 이름이다.
    • If-Modified-Since - 특정 날짜 이후에 Resource가 변경되었을 경우에만 Resource를 가져온다.
    • Authorization - Client가 Server에게 제공하는 인증 자체에 대한 정보이다.
    • Cookie - Server에게 Token을 전달할 때 사용한다.
  • Response Headers - Resource 표현 방식, 보안 등을 포함한 Response에 대한 상세한 정보를 제공한다.
  • Entity Headers - Caching을 포함한 Body에 대한 상세한 정보를 제공하며, 짧은 데이터일 경우 Body 대신 해당 Header에 입력하여 사용할 수 있다.
  • Extension Headers - 내부적으로 사용하기 위해 추가적으로 구현하여 사용하는 Header이다.

분류된 Header에는 훨씬 많은 Header들이 존재한다.

Conclusion

HTTP Message 자체에 대해 배우는 Chapter이다.
다양한 Method 중 자주 사용하는 살펴보았으나 상황에 따른 적절한 Method를 알지 못하여, 다양한 Header를 배웠으나 실제 사용하는 Header를 몰라서 누락했을 수도 있다.
이 부분은 REST API를 많이 이용하는 프로젝트를 진행하면 더 깊은 이해가 가능할 것이라 생각한다.