03. HTTP 메시지

3.1 메시지의 흐름

HTTP 메시지

  • 정의: HTTP 애플리케이션 사이에서 주고받은 데이터 블록들

  • 구성: 1) 텍스트 메타 정보 + 2) 데이터(optional)

    • 텍스트 메타 정보: 메시지의 내용과 의미를 설명함

  • 방향: 인바운드, 아웃바운드, 업스트림, 다운스트림

3.1.1 인바운드: 서버 방향 송신

  • 인바운드: 사용자 에이전트 → 서버

  • 아웃바운드: 서버 → 사용자 에이전트

3.1.2 다운스트림: 메시지의 방향

  • 모든 메시지는 다운스트림으로 흐른다

  • 요청/응답 메시지 모두 다운스트림으로 흐른다

  • (업스트림) 발송자 → (다운스트림) 수신자

3.2 메시지의 각 부분

  • 시작줄 + 헤더 + 본문

  • 시작줄과 헤더는 CRLF로 구분되나, 그 자리에 개행 문자가 오기도 하고, 아무 것도 안 오기도 한다. 견고한 애플리케이션이라면 이런 모든 상황을 대처할 수 있어야 한다.

3.2.1 메시지 문법

  • 요청 메시지: 서버에 동작 요구

  • 응답 메시지: 요청의 결과를 클라이언트에게 돌려줌

    # 요청 메시지
    GET /specials/saw-blade.gif HTTP/1.0
    Host: www.joes-hardware.com
    
    <메서드> <요청 URL> <버전>
    <헤더>
    
    <엔티티 본문>
    
    # 응답 메시지
    HTTP/1.0 200 OK
    Content-Type: image/gif
    Content-length: 8572
    
    <버전> <상태 코드> <사유 구절>
    <헤더>
    
    <엔티티 본문>

요청 URL

  • 요청 대상 리소스의 완전한 URL 또는 URL의 경로 구성 요소

  • 불완전한 URL이더라도 서버는 생략된 호스트/포트가 자신을 가리키는 것으로 간주함

사유 구절

  • 상태 코드의 사람이 이해할 수 있는 버전

  • 특별한 규칙 없음

  • HTTP/1.0 200 NOT OKHTTP/1.0 200 OK는 동등하게 성공을 의미하는 것으로 처리

엔티티 본문

  • 임의의 데이터 블록

  • 엔티티 블록을 포함하지 않는 메시지들은 그냥 CRLF로 끝남

3.2.2 시작줄

메서드

3.3 메서드

상태 코드

3.4 상태 코드

버전 번호

  • 요청, 응답 메시지에 모두 포함

  • 응답을 보낸 애플리케이션이 이해하는 가장 높은 HTTP 버전을 가리킴

  • HTTP 대화 상대의 능력과 메시지 형식에 대한 단서

  • HTTP 버전을 소수라고 생각하면 안 됨 (ex. HTTP/2.22는 HTTP/2.3보다 크다)

3.2.3 헤더

헤더 분류

  • 일반 헤더: 요청, 응답 양쪽에 모두 나타날 수 있음

  • 요청 헤더: 요청에 대한 부가 정보 제공

  • 응답 헤더: 응답에 대한 부가 정보 제공

  • Entity 헤더: 본문 크기와 콘텐츠 혹은 리소스 그 자체를 서술

  • 확장 헤더: 명세에 정의되지 않은 새로운 헤더

헤더를 여러 줄로 나누기

  • 긴 헤더 줄을 여러 줄로 쪼개서 더 읽기 좋게 만들 수 있다.

    # 두 헤더 줄은 같음
    Server: Test Server
        Version 1.0
    Server: Test Server Version 1.0

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