HTTP 범위 요청

[Network] HTTP 범위 요청


본 내용은 MDN HTTP 범위 요청을 보고 공부, 정리한 내용입니다.

HTTP 범위 요청이란, 이를 지원하는 서버의 리소스의 일부만 클라이언트가 요청할 수 있는 기능을 말한다. 대표적으로 대형 미디어의 일시정지 혹은 다시 시작 기능에 HTTP 범위 요청이 사용된다.

서버의 부분 요청 지원 확인

HTTP 범위 요청은 서버가 이를 지원해야 클라이언트가 사용할 수 있다. HTTP 응답 헤더 중 “Accept-Ranges” 헤더가 HTTP 범위 요청과 관련된 헤더이다.

예를 들어, Accept-Ranges: bytes 헤더가 HTTP 응답 메세지에 존재한다면 해당 서버에 범위 요청 시 byte 단위로 범위 요청할 수 있음을 의미한다.

범위 요청을 지원하지 않는 서버는 Accept-Ranges 헤더를 제공하지 않거나, Accept-Ranges: none 과 같이 명시적으로 나타낸다.


서버에 범위 요청하는 방법

클라이언트는 서버에게 단일 범위를 요청할 수도, 다중 범위를 요청할 수도 있다.

클라이언트는 Range 헤더를 이용하여 범위 요청을 수행할 수 있다.

단일 범위

HTTP 요청 헤더에 Range: bytes=0-1023 과 같이 헤더를 추가해 주면 된다.

1
2
3
4
// curl 사용한 HTTP 요청 방법
// -i 옵션은 HTTP 응답 헤더를 터미널에 출력하기 위해, -H 옵션은 HTTP 요청 메세지에 
// Range 헤더를 추가하기 위해 사용된다.
curl https://i.imgur.com/AD3MbBi.jpg -i -H "Range: bytes=0-1023"

서버가 범위 요청을 지원한다면, 206 Partial Content 상태와 함께 응답 메세지가 수신된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 위 HTTP 요청에 대한 서버의 응답
HTTP/1.1 206 Partial Content
Connection: keep-alive
Content-Length: 1024                             // 1024 bytes를 요청했으므로 길이가 1024
Last-Modified: Thu, 25 Aug 2016 05:39:35 GMT
ETag: "b690a7ce4be22e9da6e6c4fef80a3c7e"
Content-Type: image/jpeg
cache-control: public, max-age=31536000
Accept-Ranges: bytes
Age: 979518
Content-Range: bytes 0-1023/87345                // 반환된 리소스가 전체 리소스 중 어느 Range에 속하는지 알려줌
Accept-Ranges: bytes
Date: Thu, 15 Oct 2020 02:33:13 GMT
X-Served-By: cache-bwi5148-BWI, cache-bur17540-BUR
X-Cache: HIT, HIT
X-Cache-Hits: 1, 0
X-Timer: S1602729193.119467,VS0,VE1
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Origin: *
Server: cat factory 1.0
X-Content-Type-Options: nosniff

서버가 범위 요청을 지원하지 않는다면, 200 OK 상태와 함께 리소스 전체가 반환된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 범위 요청을 지원하지 않는 리소스에 대해 Range 헤더로 범위 요청 수행
curl https://www.youtube.com/watch?v=EwTZ2xpQwpA -i -H "Range: bytes=0-1023"

// 이에 대한 서버의 응답
HTTP/1.1 200 OK
Expires: Tue, 27 Apr 1971 19:44:06 GMT
X-Frame-Options: SAMEORIGIN
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
P3P: CP="This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=ko for more info."
Transfer-Encoding: chunked
Date: Thu, 15 Oct 2020 02:48:55 GMT
Server: YouTube Frontend Proxy
X-XSS-Protection: 0
Set-Cookie: VISITOR_INFO1_LIVE=FHc_Hgs3NpI; path=/; domain=.youtube.com; secure; expires=Tue, 13-Apr-2021 02:48:55 GMT; httponly; samesite=None
Set-Cookie: YSC=U9ScXZMLYPI; path=/; domain=.youtube.com; secure; httponly; samesite=None
Set-Cookie: GPS=1; path=/; domain=.youtube.com; expires=Thu, 15-Oct-2020 03:18:55 GMT
Alt-Svc: h3-Q050=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-27=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-T050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"

// 이하 반환된 전체 리소스..
<!doctype html><html  style="font-size: 10px;font-family: Roboto, Arial, sans-serif;" lang="ko-KR" dir="ltr" gl="KR"><head><meta

다중 범위

다중 범위 요청 방법은 단일 요청과 동일하다. 다만 범위를 콤마(,)를 이용하여 여러 개 적어주면 된다.

MDN 문서와 다른 URL로 다중 범위 테스트를 진행했을 땐 범위 요청이 실패하고 200 OK 상태코드가 반환되었다. (물론 이 URL이 범위 요청을 지원함을 확인하고 실습했다.) 이를 보아 다중 범위로 요청 가능한 리소스가 따로 있다는 추측이 가능하다.

아래는 curl MDN의 다중 범위 요청 예시 코드와, 필자의 cmd로 요청을 날려 받은 응답 헤더이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 범위 요청 지원하는 서버에 다중 범위 요청
curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"

// 서버의 응답
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Age: 223879
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 15 Oct 2020 07:15:35 GMT
Etag: "3147526947+ident"
Expires: Thu, 22 Oct 2020 07:15:35 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (oxr/8310)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 282

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 0-50/1256

<!doctype html>
<html>
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1256

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--

MDN 문서에서는 서버가 Content-Type:multipart/byteranges; boundary=~ 와 같이 해당 응답이 다중 요청에 대한 응답임을 알리고, 구분선과 함께 하단에 각 범위에 대해 Content-Type과 Content-Range가 주어진다고 설명하고 있다.

하지만 필자가 실습할 때는 위 헤더 대신 Content-Type: text/html charset=UTF-8 이 반환되었다.

조건 분할 요청

이전에 배웠던 조건부 요청의 부분 다운로드에서, 이어서 다운로드를 할 때 이전에 받은 내용과 달라진 점이 있는지 확인하는 절차를 공부했었다. 다중 범위 요청에서도 이에 대한 점을 고려해야 한다.

If-Range 헤더에 ETag 혹은 Last-Modified 값 중 하나를 이용하여 리소스의 변경 여부를 확인할 수 있다. 리소스가 변경되지 않은 경우 206 Partial Content 상태코드와 함께 요청한 범위의 리소스가 반환되고, 변경되었다면 200 OK와 함께 전체 리소스가 반환된다.

1
2
// If-Range에 Last-Modified 값을 사용한 예시
If-Range: Wed, 21 Oct 2015 07:28:00 GMT

범위 요청 응답

  • 범위 요청이 성공하면 206 Partial Content 상태코드와 함께 요청한 범위의 리소스가 반환된다.
  • 요청한 범위가 리소스 전체 범위를 벗어난 경우, 416 Requested Range Not Satisfiable이 반환된다.
  • 범위 요청을 지원하지 않는 경우, 200 OK 상태코드와 함께 전체 리소스를 반환한다.
0%