HTTP 요청/응답 스펙 간략히 이해하기 최근 La Scala 코딩단에서 Scala로 정적서버를 구현하는 스터디를 진행하게 되면서 HTTP 스펙을 다시 보게되었다. 웹개발을 하다보니 HTTP 프로토콜을 많이 사용해서 익숙하기는 하지만 그렇다고 스펙을 찬찬히 본적은 없었기에 이번 기회를 삼아서 스펙을 좀 살펴보았고 HTTP 스펙을 잘 아시는 셈틀노리님의 설명도 들었다. HTTP 1.1의 스펙은 IETF에 잘 나와있다. 일반적으로 웹프레임워크에서 대부분 처리해줘서 직접 헤더를 다뤄본 적은 없기 때문에 스터디의 범위에는 포함되어 있지 않았지만 HTTP 스펙을 좀 이해해보자는 차원에서 헤더 파싱도 간단하게 나마 시도해 봤었다. 스펙의 양이 아주 많지는 않은데 그렇다고 다 읽어본 것은 아니고 필요한 부분만 좀 찾아보았는데 셈틀노리님이 정리해서 설명도 해주었기 때문에 간단하게 나마 정리한다. Request 요청 메시지는 스펙상 다음과 같이 생겼다. Request-Line *(( general-header | request-header | entity-header ) CRLF) CRLF [ message-body ] 간단히 말하면 첫줄은 Request-Line이 오고 이어서 여러 종류의 헤더가 나온 다음에 줄바꿈을 두번하고(한줄 건너띄고) 메시지 바디가 오게된다. Request Line 요청의 첫 줄은 Request Line이라고 부르는데 스펙상은 Method SP Request-URI SP HTTP-Version CRLF 와 같이 정의하는데 보통 다음과 같이 생겼다. GET /index.html HTTP/1.1 맨 앞의 GET은 요청 Method를 의미하는데 OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT 8가지가 있다. OPTIONS : 요청 URI에서 사용할 수 있는 Method를 물어본다.(스펙 참고) GET : 요청 URI의 정보를 가져온다.(스펙 참고) HEAD : GET 요청에서 body는 제외하고 헤더만 가져온다.(스펙 참고) POST : 요청 URI의 리소스의 새로운 정보를 보낸다.(스펙 참고) PUT : 요청 URI에 저장될 정보를 보낸다. (스펙 참고) DELETE : 요청 URI의 리소스를 삭제한다.(스펙 참고) TRACE : 보낸 메시지를 다시 돌려보낸다. (스펙 참고) CONNECT : 프록시에 사용하기 위해 예약된 메서드이다.(스펙 참고) 메서드 다음에는 요청 URI가 온다.(/index.html 부분) 말그대로 URI이고 절대경로의 URI가 될수도 있고 *이 될수도 있다. Request Line의 마지막에는 HTTP 버전을 의히한다. 스펙상으로는 "HTTP" "/" 1*DIGIT "." 1*DIGIT 와 같이 정의되는데 현재 HTTP/1.0과 HTTP/1.1이 있다. 마지막에는 <CRLF>가 있어야 한다. 즉, 줄바꿈을 한다는 얘기인데 CR은 carriage return(13)이고 LF는 linefeed(10)이다.(각 기호에 대한 정의는 스펙의 Basic Rule부분에 나와있다.) 추가: 김관래의 제보로 PATCH 메서드 추가합니다. partial resource modification 용도라는데 HTTP 1.1 스펙에 안들어있는걸 보면 진행중인 상태가 아닐까 혼자 추측해 봅니다. PATCH for HTTP Headers Request-Line 다음에는 header가 위치하는데 앞에서 본 스펙대로 general-header, request-header, entity-header 3가지 종류가 있고 요청에 따라 필요한 헤더만 사용하게 된다. General Header에는 Cache-Control, Connection, Date, Pragma, Trailer, Transfer-Enco, Upgrade, Via, Warning가 있고 Request Header에는 Accept, Accept-Charset, Accept-Encoding, Accept-Language, Authorization, Expect, From, Host, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Max-Forwards, Proxy-Authorization, Range, Referer, TE, User-Agent등이 있고 Entity Header에는 Allow, Content-Encoding, Content-Language, Content-Length, Content-Location, Content-MD5, Content-Range, Content-Type, Expires, Last-Modified, extension-header가 있다. 헤더는 name : content의 형식이 되는데 content 부분은 각 헤더에 대한 상세 내용을 확인해 보면 되는데 각 값들은 공백이나 탭으로 구분될 수 있고 각 헤더는 CRLF로 구분된다. Response 응답 메시지는 다음과 같이 정의되어 있다. Status-Line *(( general-header | response-header | entity-header ) CRLF) CRLF [ message-body ] 첫줄이 요청라인대신에 상태라인인것과 요청헤더 대신 응답헤더가 들어간 것만 빼면 요청 메시지와 동일한 형태이다. Status Line Status Line은 HTTP-Version SP Status-Code SP Reason-Phrase CRLF로 정의되어 있고 보통 다음과 같이 생겼다. HTTP/1.1 200 OK HTTP 버전은 요청부분에서 설명한 것과 동일하고 상태코드(Status-Code)는 흔히 보는 3자리 숫자로 된 상태를 나타내는 코드로 각 번호대 별로 다음과 같은 의미를 가지고 있다. 1xx : 정보성 2xx : 성공 3xx : 리다이렉트 4xx : 클라이언트 오류 5xx : 서버 오류 각 상태코드에 대한 설명도 스펙에 잘 나와있다. Headers 헤더 부분의 General Header와 Entity Header는 요청부분에서 설명한 것과 동일하고 Response Header는 Accept-Ranges, Age, ETag, Location, Proxy-Authenticate, Retry-After, Server, Vary, WWW-Authenticate가 있다.