03. HTTP 메시지
3.1 메시지의 흐름
HTTP 메시지
정의: HTTP 애플리케이션 사이에서 주고받은 데이터 블록들
구성: 1) 텍스트 메타 정보 + 2) 데이터(optional)
텍스트 메타 정보: 메시지의 내용과 의미를 설명함
방향: 인바운드, 아웃바운드, 업스트림, 다운스트림
3.1.1 인바운드: 서버 방향 송신
인바운드: 사용자 에이전트 → 서버
아웃바운드: 서버 → 사용자 에이전트
3.1.2 다운스트림: 메시지의 방향
모든 메시지는 다운스트림으로 흐른다
요청/응답 메시지 모두 다운스트림으로 흐른다
(업스트림) 발송자 → (다운스트림) 수신자
3.2 메시지의 각 부분
시작줄 + 헤더 + 본문
시작줄과 헤더는 CRLF로 구분되나, 그 자리에 개행 문자가 오기도 하고, 아무 것도 안 오기도 한다. 견고한 애플리케이션이라면 이런 모든 상황을 대처할 수 있어야 한다.
3.2.1 메시지 문법
요청 메시지: 서버에 동작 요구
응답 메시지: 요청의 결과를 클라이언트에게 돌려줌
요청 URL
요청 대상 리소스의 완전한 URL 또는 URL의 경로 구성 요소
불완전한 URL이더라도 서버는 생략된 호스트/포트가 자신을 가리키는 것으로 간주함
사유 구절
상태 코드의 사람이 이해할 수 있는 버전
특별한 규칙 없음
HTTP/1.0 200 NOT OK
와HTTP/1.0 200 OK
는 동등하게 성공을 의미하는 것으로 처리
엔티티 본문
임의의 데이터 블록
엔티티 블록을 포함하지 않는 메시지들은 그냥 CRLF로 끝남
3.2.2 시작줄
메서드
상태 코드
버전 번호
요청, 응답 메시지에 모두 포함
응답을 보낸 애플리케이션이 이해하는 가장 높은 HTTP 버전을 가리킴
HTTP 대화 상대의 능력과 메시지 형식에 대한 단서
HTTP 버전을 소수라고 생각하면 안 됨 (ex. HTTP/2.22는 HTTP/2.3보다 크다)
3.2.3 헤더
헤더 분류
일반 헤더: 요청, 응답 양쪽에 모두 나타날 수 있음
요청 헤더: 요청에 대한 부가 정보 제공
응답 헤더: 응답에 대한 부가 정보 제공
Entity 헤더: 본문 크기와 콘텐츠 혹은 리소스 그 자체를 서술
확장 헤더: 명세에 정의되지 않은 새로운 헤더
헤더를 여러 줄로 나누기
긴 헤더 줄을 여러 줄로 쪼개서 더 읽기 좋게 만들 수 있다.
3.2.4 엔티티 본문
이미지, 비디오, HTML 문서, 소프트웨어 애플리케이션, 신용카드 트랜잭션, 전자우편 등 여러 종류의 디지털 데이터
3.2.5 버전 0.9 메시지
요청: 메서드 + 요청 URL (ex.
GET /specials/saw-blade.gif
)응답: 엔티티
버전 정보, 상태 코드, 사유 구절, 헤더 등이 없음
3.3 메서드
클라이언트 측에서 서버가 리소스에 대해 수행해주길 바라는 동작을 요청 메시지에 전달
한 단어로 되어 있음 (ex.
GET
,HEAD
,POST
)확장 메서드: 특정 서버가 추가로 구현한 HTTP 메서드
모든 서버가 모든 메서드를 구현하지는 않음
메서드는 대부분 제한적으로 사용됨 (아무나 메서드를 사용할 수 없음)
3.3.1 안전한 메서드
HTTP 요청의 결과로 서버에 어떤 작용도 없는 것
안전한 메서드가 서버에 작용을 유발하지 않는다는 보장은 없음
안전한 메서드의 목적은 안전하지 않은 메서드가 사용될 때 사용자들에게 그 사실을 알려주는 것임
3.3.2 GET
서버에게 리소스를 달라고 요청
HTTP/1.1은 서버가 GET을 구현할 것을 요구함
3.3.3 HEAD
GET처럼 행동하지만, 응답으로 헤더만 돌려주는 것
GET으로 얻는 헤더와 같은 헤더이고 엔티티 본문만 없는 것
리소스가 삭제되거나 변경되었는지 검사
리소스를 가져오지 않고 타입 등 정보를 알아냄
HTTP/1.1 준수를 위해서는 HEAD가 반드시 구현되어 있어야 함
3.3.4 PUT
서버에 요청의 본문을 가지고 요청 URL의 이름대로 새 문서를 만드는 것
이미 해당 URL이 존재한다면 요청의 본문으로 교체하는 것
많은 웹 서버가 PUT에 사용자 비밀번호를 이용해 로그인할 것을 요구함
3.3.5 POST
서버에 입력 데이터를 전송 (ex. HTML 폼)
데이터는 서버로 전송되고, 서버는 이를 모아서 필요로 하는 곳(게이트웨이 등)에 보냄
정리한 사람 주: PUT과 POST의 차이는 요청 URL
3.3.6 TRACE
요청이 방화벽, 프락시, 게이트웨이 등 여러 애플리케이션을 통과할 수 있기 때문에, 클라이언트가 자신의 요청이 뮥적지 서버에 도달했을 때 어떻게 보이는지 TRACE를 통해 알 수 있다.
요청은 엔티티 본문과 함께 보낼 수 없으며, 응답에는 서버가 받은 요청이 그대로 들어 있다.
loopback 진단
마지막 단계에 있는 서버는 자신이 받은 요청 메시지를 본문에 넣어 응답
클라이언트는 자신과 목적지 서버 사이에 있는 모든 HTTP 애플리케이션의 요청/응답 연쇄를 따라감
프락시나 다른 애플리케이션이 요청에 어떤 영향을 미치는지 확인
문제점: 중간 애플리케이션들이 TRACE 요청을 일관되게 다루지 않을 수 있음
3.3.7 OPTIONS
리소스에 접근하지 않고 서버에게 특정 리소스에 대해 어떤 메서드가 지원되는지 물어봄
3.3.8 DELETE
서버에게 요청 URL의 리소스를 삭제할 것을 요청
HTTP 명세는 서버가 클라이언트에게 알리지 않고 요청을 무시하는 것을 허용함. 따라서 삭제가 보장되지는 않는다.
3.3.9 확장 메서드
HTTP/1.1 명세에 정의되지 않은 메서드
ex. WebDav HTTP 확장: LOCK(리소스 잠금), MKCOL(문서 생성), COPY(복사), MOVE(이동)
"엄격하게 보내고 관대하게 받아들여라"
프락시는 알려지지 않은 메서드가 담긴 메시지도 다운스트림 서버로 전달한다.
해당 메서드가 end-to-end에 영향을 끼친다면, 501 Not Implemented 상태 코드로 응답한다.
3.4 상태 코드
대표적인 상태 코드
200 OK: 성공 요청한 모든 데이터가 응답 본문에 들어 있다.
401 Unauthorized: 사용자 이름과 비밀번호를 입력해야 한다.
404 Not Found: 서버가 요청 URL에 해당하는 리소스를 찾지 못했다.
다섯 가지 분류
인식할 수 없는 상태 코드를 받게 되면 그것이 포함되는 범위의 일부라고 가정해야 함
ex. 515는 다른 5XX 메시지들과 마찬가지로 서버 에러를 의미할 것
3.4.1 100-199: 정보성 상태 코드
HTTP/1.1에서 도입되었으며 감수할 만한 가치가 있는지 논란이 있음
100 Continue
엔티티 본문을 서버가 받아들일 것인지 확인할 때 사용
클라이언트는 100 Continue를 받고 나머지 요청을 계속 이어 보내야 함
서버는 100 Continue를 보낸 이후 요청을 받아 응답해야 함
클라이언트와 100 Continue
클라이언트는 첫 번째 요청의 헤더에
Expect: 100-continue
를 보내야 함최적화: 서버가 다루거나 사용할 수 없는 큰 엔티티를 보내지 않기 위함
클라이언트는 서버가 100-continue 응답을 내려주기를 마냥 기다리면 안 되고, 약간의 타임아웃 후에 그냥 엔티티를 보내야 함
클라이언트는 예상하지 못한 100 Continue 응답에도 대비해야 함
서버와 100 Continue
요청 헤더에
Expect: 100-continue
가 있는 경우에만 100 Continue 응답을 주어야서버가 응답을 보내기 전 엔티티의 일부 혹은 전체를 받았다면, 100 Continue를 생략하고 해당 요청에 대한 응답만 보내면 됨
100 Continue 요청을 받고 본문을 읽기 전 요청을 끝내기로 결정했을 때, 응답을 보내고 연결을 닫아 버리면 클라이언트는 응답을 받을 수 없게 됨 (cf. 4장 TCP 끊기와 리셋 에러)
프락시와 100 Continue
프락시가 100 Continue 요청을 받았을 때,
다음 홉 서버가 HTTP/1.1을 따르거나, 어떤 버전을 따르는지 모른다면, 요청을 다음으로 전달
다음 홉 서버가 HTTP/1.1 이전 버전이라면 417 Expecation Failed 에러로 응답
3.4.2 200-299: 성공 상태 코드
3.4.3 300-399: 리다이렉션 상태 코드
리소스가 옮겨진 사실과 어디서 찾을 수 있는지(Location 헤더, optional)를 알려줌
리다이렉트될 URL에 대한 링크와 설명을 포함하면 좋음
클라이언트의 복사본이 여전히 최신인지, 원래 서버에 있는 리소스가 수정되었는지 검사
302, 303, 307은 HTTP/1.0과 1.1에서 다름
서버가 POST 요청을 받은 뒤, 클라이언트가 리다이렉션 URL을 받고, GET 요청으로 리다이렉트를 따라가기를 기대하는 상황이라면
HTTP 1.0 클라이언트: 302 응답을 받고 GET 요청으로 Location 헤더에 있는 URL을 따라감
HTTP 1.1 클라이언트: 303 응답을 받고 GET 요청으로 Location 헤더에 있는 URL을 따라감 (307은 그대로 POST 메소드 사용할 때)
3.4.4 400-499: 클라이언트 에러 상태 코드
클라이언트에서 올바른 요청을 보냈지만 서버에서 에러 발생
3.5 헤더
<이름> <콜론(:)> (<공백>) <값> <CRLF>가 순서대로 나타나는 0개 이상의 헤더들
HTTP/1.1과 같은 몇몇 버전의 HTTP는 요청이나 응답에 특정 헤더가 포함되어야만 유효한 것으로 간주
3.5.1 일반 헤더
클라이언트, 서버 모두 사용
메시지에 대한 기본적 정보 제공
매번 서버로부터 객체를 가져오는 대신 사본으로 캐시해주는 헤더
요청 메시지에 사용
클라이언트의 선호나 능력
서버가 더 나은 응답을 주는 데 활용
Accept 관련 헤더
프락시 요청 헤더
응답 메시지에 사용
협상 헤더
서버에 여러 가지 표현이 가능한 문서가 있을 때, 서버와 클라이언트가 그 중 어떤 표현을 택할 것인지 협상 지원
ex. 서버에 한국어, 영어로 번역된 HTML 문서가 있을 때
3.5.4 엔티티 헤더
엔티티 본문에 대한 헤더
요청과 응답 메시지 모두에 나타날 수 있음
콘텐츠 헤더
엔티티 캐싱 헤더
언제 어떻게 캐시가 되어야 하는지, 캐시된 사본이 유효한지, 리소스가 유효하지 않게 되는 시점이 언제인지 등
cf. 확장 헤더
HTTP 명세에 없는 헤더
HTTP 애플리케이션은 확장 헤더의 의미를 몰라도 용인하고 전달할 수 있어야 함
Last updated