HTTP 1.1의 스펙은 IETF에 잘 나와있다. 일반적으로 웹프레임워크에서 대부분 처리해줘서 직접 헤더를 다뤄본 적은 없기 때문에 스터디의 범위에는 포함되어 있지 않았지만 HTTP 스펙을 좀 이해해보자는 차원에서 헤더 파싱도 간단하게 나마 시도해 봤었다. 스펙의 양이 아주 많지는 않은데 그렇다고 다 읽어본 것은 아니고 필요한 부분만 좀 찾아보았는데 셈틀노리님이 정리해서 설명도 해주었기 때문에 간단하게 나마 정리한다.
Request
요청 메시지는 스펙상 다음과 같이 생겼다.
Request-Line
*(( general-header | request-header | entity-header ) CRLF)
CRLF
[ message-body ]
*(( 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 : 프록시에 사용하기 위해 예약된 메서드이다.(스펙 참고)
추가: 김관래의 제보로 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 ]
*(( 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 OKHTTP 버전은 요청부분에서 설명한 것과 동일하고 상태코드(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가 있다.
좋은 내용 정리 감사합니다.
전부터 계속 들여봐야지 하던 내용들인데 아무래도 레퍼런스 문서는 너무 딱딱해서
이해하기가 너무 어려워서 차일피일 미루게 되네요;;;;
저도 미루고 미루다.. 이번기회에 좀 살펴봤네요. 나중에 시간내서 찬찬히 보긴 해야할텐데요.
HTTP 메쏘드는 저에게 너무 딱딱한 이야기였지만 덕분에 이해하고 갑니다.
감사합니다.
요즘은 HTTP가 거의 필수라서 스펙 등 다양한 문서를 읽어보시면 좋습니다.
감사합니다. 잘보고 갑니다
안녕하세요. jsoup 관련한 정보 검색 하다가 좋은 내용 보고 갑니다~
궁금한게 하나 있는데 html get방식으로 가져올 때 head 태그에 있는 내용만 뽑아오게 하기 위해서
Connection.Response response = Jsoup.connect(URLDecoder.decode("http://www.google.com/", "UTF-8"))
.userAgent("Mozilla")
.method(Connection.Method.HEAD)
.execute();
Document doc = response.parse();
로 head 내용만 뽑아 볼려고 했는데 실질적으로는 body 내용까지 다 내려오더라고요. 혹시 사용법이 잘못되거나 다른 방법이 있는지 아시면 답변 주시면 감사하겠습니다 ^^:
Jsoup이면 Java 라이브러리군요. 제가 한번도 사용해 본적이 없어서 사용방법을 잘 모르겠습니다. 일반적인 HTML 파서를 생각하면 응답을 파싱했을때 본문의 내용이 모두 있는게 정상적으로 보입니다. 파싱하신 doc에서 head 태그에 있는거만 따로 추출하셔야 합니다.
답변을 적다보지 약간 헷갈리는데 HTML의 head 태그가 아니라 HTTP의 header가 필요하신거라면 HTML 파서가 아니라 HTTP 요청 라이브러리에서 헤더만 가져오셔야 할 것 같습니다.