HTTP range requests
HTTPS range requests에 대해 확인해 본 내용 정리입니다.
아래의 사이트에서 대부분 참고하였습니다.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests
HTTP range request는 서버에게 리소스의 일부를 클라이언트로 다시 전송하도록 요청하는 것을 정의합니다.
Range requests는 랜덤 액세스를 지원하는 미디어 플레이어나 대용량 파일의 일부만 필요한 데이터 소프트웨어, 사용자가 다운로드를 일시 중지했다가 다시 시작할 수 있는 다운로드 관리자 등의 다양한 클라이언트에서 유용하게 사용될 수 있습니다.
서버가 지원하는지 확인하는 방법
HTTP response에 Accept-Ranges가 포함되는지를 확인합니다.
curl -I http://localhost/text.txt
HTTP/1.1 200 OK
Date: Mon, 11 Nov 2024 07:56:04 GMT
Server: Apache/2.4.41 (Ubuntu)
Last-Modified: Mon, 11 Nov 2024 07:55:10 GMT
ETag: "d3-6269e6b7ab28a"
Accept-Ranges: bytes
Content-Length: 211
Vary: Accept-Encoding
Content-Type: text/plain
Accept-Ranges: bytes
가 없다면 지원하지 않는 서버입니다.
서버의 응답
테스트 파일
cat /var/www/html/text.txt
0:ABCDEFGH1:IJKLMNOP2:QRSTUVWX3:YZ1234564:789ABCDE5:FGHIJKLM6:NOPQRSTU7:VWXYZ1238:456789AB9:CDEFGHIJ10:KLMNOPQ11:RSTUVWX12:YZ1234513:6789ABC14:DEFGHIJ15:KLMNOPQ16:RSTUVWX17:YZ1234518:6789ABC19:DEFGHIJ20:KLMNOPQ
정상 범위
multipart ranges를 요청하는 예제입니다.
curl -v -H "Range: bytes=0-50, 100-150" http://localhost/text.txt
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /text.txt HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Range: bytes=0-50, 100-150
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 206 Partial Content
< Date: Mon, 11 Nov 2024 07:57:36 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Last-Modified: Mon, 11 Nov 2024 07:55:10 GMT
< ETag: "d3-6269e6b7ab28a"
< Accept-Ranges: bytes
< Content-Length: 291
< Vary: Accept-Encoding
< Content-Type: multipart/byteranges; boundary=abc428311b9ac486
<
--abc428311b9ac486
Content-type: text/plain
Content-range: bytes 0-50/211
0:ABCDEFGH1:IJKLMNOP2:QRSTUVWX3:YZ1234564:789ABCDE5
--abc428311b9ac486
Content-type: text/plain
Content-range: bytes 100-150/211
10:KLMNOPQ11:RSTUVWX12:YZ1234513:6789ABC14:DEFGHIJ1
--abc428311b9ac486--
* Connection #0 to host localhost left intact
정상적인 응답의 경우 206 Partial Content를 확인할 수 있습니다.
비정상 범위
curl -v -H "Range: bytes=1000-1050" http://localhost/text.txt
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /text.txt HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Range: bytes=1000-1050
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 416 Requested Range Not Satisfiable
< Date: Mon, 11 Nov 2024 08:00:32 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>416 Requested Range Not Satisfiable</title>
</head><body>
<h1>Requested Range Not Satisfiable</h1>
<p>None of the range-specifier values in the Range
request-header field overlap the current extent
of the selected resource.</p>
<hr>
<address>Apache/2.4.41 (Ubuntu) Server at localhost Port 80</address>
</body></html>
* Connection #0 to host localhost left intact
범위가 잘못된 경우 416 Range Not Satisfiable 응답이 확인됩니다.
multipart requests error
curl -v -H "Range: bytes=2000-2050, 1000-1050" http://localhost/text.txt
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /text.txt HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Range: bytes=2000-2050, 1000-1050
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 416 Requested Range Not Satisfiable
< Date: Mon, 11 Nov 2024 08:17:03 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=iso-8859-1
<
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>416 Requested Range Not Satisfiable</title>
</head><body>
<h1>Requested Range Not Satisfiable</h1>
<p>None of the range-specifier values in the Range
request-header field overlap the current extent
of the selected resource.</p>
<hr>
<address>Apache/2.4.41 (Ubuntu) Server at localhost Port 80</address>
</body></html>
* Connection #0 to host localhost left intact
잘못된 range를 Range: bytes=2000-2050, 1000-1050
로 포함하고 있습니다.
문서에는 아래와 같이 Content-Range
가 포함된다고 하는데 서버의 구현 차이인지는 모르겠습니다.
The 416 response message should contain a Content-Range indicating an unsatisfied range (that is a '*') followed by a '/' and the current length of the resource, e.g., Content-Range: bytes */12777
https://www.rfc-editor.org/rfc/rfc9110#status.416
A server that generates a 416 response to a byte-range request SHOULD generate a Content-Range header field specifying the current length of the selected representation (Section 14.4).
For example:
HTTP/1.1 416 Range Not Satisfiable
Date: Fri, 20 Jan 2012 15:41:54 GMT
Content-Range: bytes */47022
비정상 범위가 혼합된 경우
curl -v -H "Range: bytes=0-50, 1000-1050" http://localhost/text.txt
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /text.txt HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Range: bytes=0-50, 1000-1050
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 206 Partial Content
< Date: Mon, 11 Nov 2024 08:00:17 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Last-Modified: Mon, 11 Nov 2024 07:55:10 GMT
< ETag: "d3-6269e6b7ab28a"
< Accept-Ranges: bytes
< Content-Length: 51
< Vary: Accept-Encoding
< Content-Range: bytes 0-50/211
< Content-Type: text/plain
<
* Connection #0 to host localhost left intact
0:ABCDEFGH1:IJKLMNOP2:QRSTUVWX3:YZ1234564:789ABCDE5%
multipart ranges의 경우 일부가 범위에 맞다면 잘못된 범위의 값이 있어도 206 Partial Content
응답으로 처리하는 것을 확인할 수 있습니다.
curl -v -H "Range: bytes=1000-1050, 0-50" http://localhost/text.txt
* Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /text.txt HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> Range: bytes=1000-1050, 0-50
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 206 Partial Content
< Date: Mon, 11 Nov 2024 08:04:13 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Last-Modified: Mon, 11 Nov 2024 07:55:10 GMT
< ETag: "d3-6269e6b7ab28a"
< Accept-Ranges: bytes
< Content-Length: 51
< Vary: Accept-Encoding
< Content-Range: bytes 0-50/211
< Content-Type: text/plain
<
* Connection #0 to host localhost left intact
0:ABCDEFGH1:IJKLMNOP2:QRSTUVWX3:YZ1234564:789ABCDE5%
range의 순서가 바뀌어도 동일합니다.
첫 번째 정상 범위의 multipart ranges와 다른 점은 Content-Type: multipart/byteranges;
이 아닌 Content-Type: text/plain
인 점입니다.
정상 범위에 대한 Content-Range: bytes 0-50/211
가 표시됨을 확인할 수 있습니다.