HTTP 범위 헤더


81

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 를 읽고 파일 다운로드를 계속하는 방법을 알아 내려고했습니다.

예를 들어 파일 길이가 100 바이트이고 모두 100 바이트라고 가정합니다. 그러나 예상되는 파일 크기가 무엇인지 모르기 때문에 파일을 요청하고 다음과 같은 Range 헤더를 지정합니다.

Range: bytes=100-

유효한 범위 요청입니까?


5
음, 그 아래의 예에서는 'bytes = 9500-'이 유효한 것으로 인용되어 있으므로 ....
Wrikken

1
가장 최근의 참조는 RFC7233-httpwg.github.io/specs/rfc7233.html
Mark Nottingham

2
먼저 HEAD 요청을하고 파일 길이를 확인할 수 있습니다.
Matheus Rocha

답변:


54

구문 적으로 유효한 요청이지만 만족스러운 요청은 아닙니다. 해당 섹션에서 더 자세히 살펴보면 다음을 참조하십시오.

구문 상 유효한 바이트 범위 세트가 첫 번째 바이트 위치가 엔티티 본문의 현재 길이보다 작은 하나 이상의 바이트 범위 스펙 또는 비가있는 접미사 바이트 범위 스펙을 포함하는 경우 -접미사 길이가 0이면 바이트 범위 집합이 만족 스럽습니다. 그렇지 않으면 바이트 범위 세트가 만족스럽지 않습니다. 바이트 범위 세트가 만족스럽지 않으면 서버는 상태가 416 (요청 된 범위가 만족스럽지 않음)의 응답을 반환해야합니다 (SHOULD) . 그렇지 않으면 서버는 엔티티 본문의 만족할 수있는 범위를 포함하는 206 (부분 콘텐츠) 상태의 응답을 반환해야합니다 (SHOULD).

따라서 귀하의 예에서 서버는 해당 파일에 대해 유효한 바이트 범위가 아니기 때문에 416을 반환해야한다고 생각합니다.


그렇다면 클라이언트가 먼저 콘텐츠 길이를 파악한 다음 수학을 수행하고 실제 콘텐츠를 가져 오기 위해 HEAD 호출을하지 않고 다운로드를 재개 할 수있는 방법이 있습니까? 내가 좋아하는 주소 개방의 일종을 의미한다 "... 나에게 이러 이러한 바이트 후 모든 바이트를 제공"
dhruvbird

5
클라이언트는 원래 요청의 모든 데이터가 있는지 이미 알고 있습니다. 원래 응답에서 Content-Length 헤더를 수신 했어야합니다. 또는 청크 인코딩 된 경우 길이가 0 인 청크를 수신하여 응답이 완료되었습니다. 이 상태를 저장하지 않고 디스크에 바이트 청크 만 있으면 HEAD 요청을 수행하거나 Range 헤더를 사용하여 바이트 범위를 요청하고 416을 반환해야합니다. 모든 바이트가 있다는 것을 알고있는 응답.
Marc Novakowski

Expect-Continue를 사용하면 원하는대로 스트리밍 청크를 수행 할 수 있다고 생각합니다.
MJB

@MarcNovakowski 사실, wget의 경우와 -c 플래그를 사용하는 것을 고려하십시오. wget은 완료되는 파일에 대한 메타 데이터를 유지하지 않으므로 디스크의 파일 크기가 99 바이트라고 가정합니다. wget은 "100-"바이트 범위를 요청하며, 요청이 파일의 끝을 지나서 1 번 지났기 때문에 서버가 길이가 0 인 응답으로 응답해야한다고 생각합니다.
dhruvbird

147

Wrikken이 제안 했듯이 유효한 요청입니다. 클라이언트가 미디어를 요청하거나 다운로드를 재개 할 때도 매우 일반적입니다.

클라이언트는 종종 서버가 Accept-Ranges응답을 찾는 것 외에 범위가 지정된 요청을 처리하는지 확인하기 위해 테스트합니다 . Chrome은 항상Range: bytes=0- 동영상에 대한 첫 번째 GET 요청과 함께을 전송 하므로 무시할 수 없습니다.

클라이언트 Range:가 요청에 포함 할 때마다 형식이 잘못된 경우에도 부분 콘텐츠 (206) 응답을 기대합니다. HTML5 비디오 재생 중에 앞으로 검색하면 브라우저는 시작 지점 만 요청합니다. 예를 들면 :

Range: bytes=3744-

따라서 클라이언트가 비디오를 제대로 재생하려면 서버가 이러한 불완전한 범위 요청을 처리 할 수 ​​있어야합니다.

질문에 지정한 '범위'유형을 두 가지 방법으로 처리 할 수 ​​있습니다.

먼저, 응답에 제공된 요청 된 시작 지점으로 응답 한 다음 파일의 총 길이에서 1을 뺀 값으로 응답 할 수 있습니다 (요청 된 바이트 범위는 0 인덱싱 됨). 예를 들면 :

의뢰:

GET /BigBuckBunny_320x180.mp4 
Range: bytes=100-

응답:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/64656927

둘째, 요청에 제공된 시작점과 개방형 파일 길이 (크기)로 응답 할 수 있습니다. 전체 길이를 알 수없는 웹 캐스트 또는 기타 미디어 용입니다. 예를 들면 :

의뢰:

GET /BigBuckBunny_320x180.mp4
Range: bytes=100-

응답:

206 Partial Content
Content-Type: video/mp4
Content-Length: 64656927
Accept-Ranges: bytes
Content-Range: bytes 100-64656926/*

팁 :

항상 범위에 포함 된 콘텐츠 길이로 응답해야합니다. 범위가 시작부터 끝까지 완료되면 콘텐츠 길이는 단순히 차이입니다.

요청 : 범위 : bytes = 500-1000

응답 : Content-Range : 바이트 500-1000 / 123456

범위는 인덱스가 0이므로 Range: bytes=0-999실제로는 999가 아닌 1000 바이트를 요청하므로 다음과 같이 응답합니다.

Content-Length: 1000
Content-Range: bytes 0-999/123456

또는:

Content-Length: 1000
Content-Range: bytes 0-999/*

그러나 일부 미디어 플레이어는 파일 크기에서 기간을 알아 내려고하기 때문에 가능하면 후자의 방법을 사용하지 마십시오. 귀하의 요청이 제 직감 인 미디어 콘텐츠에 대한 것이라면 응답에 기간을 포함해야합니다. 이는 다음 형식으로 수행됩니다.

X-Content-Duration: 63.23 

이것은 부동 소수점이어야합니다. 과 달리이 Content-Length값은 정확할 필요가 없습니다. 플레이어가 동영상을 탐색하는 데 사용됩니다. 웹 캐스트를 스트리밍하고 있고 얼마나 오래 걸릴지에 대한 일반적인 생각 만 가지고 있다면, 전체를 무시하는 것보다 예상 시간을 포함하는 것이 좋습니다. 따라서 2 시간짜리 웹 캐스트의 경우 다음과 같은 내용을 포함 할 수 있습니다.

X-Content-Duration: 7200.00 

webm과 같은 일부 미디어 유형의 경우 다음과 같은 콘텐츠 유형도 포함해야합니다.

Content-Type: video/webm 

이 모든 것은 미디어, 특히 HTML5에서 제대로 재생되는 데 필요합니다. 기간을 제공하지 않으면 플레이어가 파일 크기에서 기간을 알아 내려고 할 수 있지만 정확하지는 않습니다. 이것은 괜찮고 웹 캐스트 나 라이브 스트리밍에 필요하지만 비디오 파일 재생에는 적합하지 않습니다. FFMPEG와 같은 소프트웨어를 사용하여 기간을 추출하고 데이터베이스 또는 파일 이름에 저장할 수 있습니다.

X-Content-Duration을 (를) 찬성하여 단계적으로 제거되고 Content-Duration있으므로 이것도 포함하겠습니다. "0-"요청에 대한 기본 응답에는 최소한 다음이 포함됩니다.

HTTP/1.1 206 Partial Content
Date: Sun, 08 May 2013 06:37:54 GMT
Server: Apache/2.0.52 (Red Hat)
Accept-Ranges: bytes
Content-Length: 3980
Content-Range: bytes 0-3979/3980
Content-Type: video/webm
X-Content-Duration: 2054.53
Content-Duration: 2054.53

한 가지 더, Chrome은 항상 다음과 같이 첫 번째 동영상 요청을 시작합니다.

Range: bytes=0-

일부 서버는 응답으로 일반 200 응답을 보내지 만이를 수락하지만 (하지만 재생 옵션이 제한됨) 서버가 범위를 처리하는 것보다 표시하기 위해 대신 206을 보내려고합니다. RFC 2616 은 범위 헤더를 무시해도 괜찮다고 말합니다.


콘텐츠가 기간이 고정되지 않은 라이브 비디오 스트림 인 경우 어떻게합니까?
Joel Barsotti 2014

@Joel, 당신이 그것을 모르더라도 기간을 포함하여 응답해야합니다. 이 경우 0.0을 시도하십시오. 클라이언트의 경우 일반적으로 실시간 스트림을 스캔 할 수 없기 때문에 길이는 중요하지 않습니다. 0.0이 작동하지 않으면 1000000.00과 같이 매우 높은 값을 시도하십시오.
Victor Stoddard 2014

@VictorStoddard는 클라이언트 요청에 Range 헤더가없는 일반 파일 다운로드에 청크 스트리밍을 적용 할 수 있습니까? 이 경우 서버는 어떻게 응답해야합니까?
gkiko 2015-09-23

@gkiko Chunked Transfer Encoding에서 Content-Length 대신 Transfer-Encoding 헤더를 사용하는 것 외에는 큰 차이가 없습니다. 청크는 단일 파일에서 가져올 수 있으며 서버는 청크 크기를 설정할 수 있습니다. 클라이언트는 수신 된 청크를 버퍼링하고 함께 조각해야합니다. 또는 HTTP 스트리밍은 미디어 파일의 미리 기록 된 세그먼트를 사용하여 서버에 개별 부분 (ts 파일)으로 저장됩니다. 이러한 세그먼트는 인덱스 파일에서 얻은 일반 HTTP 파일 GET 요청을 사용하여 제공됩니다. 세분화가 까다 로움을 발견했지만 그것은 몇 년 전이었습니다.
Victor Stoddard 2015 년

Content-Length : 64656927 Accept-Ranges : bytes Content-Range : bytes 100-64656926 Content-Length가 '64656827'이 아닌 이유는 무엇입니까?
iwind

7

어떤 이유로 많은 사람들이 찬성 한 Mark Novakowski 답변과는 달리 유효하고 만족스러운 요청입니다.

실제로 Wrikken이 지적했듯이 표준은 그러한 예를 보여줍니다. 실제로 Firefox는 예상대로 (206 코드로) 이러한 요청에 응답하며, 이것이 바로 점진적 다운로드를 구현하는 데 사용하는 것입니다. 즉, 폴링으로 실시간으로 커지는 긴 로그 파일의 꼬리 만 가져옵니다.


2
Marc Novakowki의 답변을 다시 읽으십시오. "satisfiable"은 그가 인용 한 RFC에서 특별한 의미를 갖는다. 요청 된 바이트가 파일 길이를 초과하므로이 요청은 만족스럽지 않습니다.
Scott Lamb

1
Firefox는 요청에 응답하는 소프트웨어 요소가 아니라 http 서버입니다
Colin D

예, 죄송합니다. Apache
Francesco Potortì

5

2019 년에 위의 Victor Stoddard의 답변에 걸림돌이되고 희망을 품고 눈에 띄는 사람들을 위해 다음 사항에 유의하십시오.

a) X-Content-Duration에 대한 지원이 Firefox 41에서 제거되었습니다 : https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/41#HTTP

b) Firefox에서만 .ogg 오디오 및 .ogv 비디오를 지원했으며 다른 유형에서는 지원하지 않았다고 생각합니다.

c) Chrome에서 전혀 지원되지 않는다는 것을 알 수 없지만 제 부분에 대한 연구가 부족할 수 있습니다. 그러나 현재 Chrome 71에서 webm 또는 ogv 비디오에 대한 존재 여부는 어떤 식 으로든 영향을 미치지 않는 것 같습니다.

d) 'Content-Duration'이 'X-Content-Duration'을 대체 한 곳을 찾을 수 없습니다. 'X-Content-Duration'이 후속 헤더 이름이있을만큼 오래 살았다 고 생각하지 않습니다.

내 생각에 이것은 현재 시간 (예 : ffpeg 파이프의 출력)을 모르는 스트림을 포함하는 webm 또는 ogv 컨테이너를 Chrome 또는 FF에 제공하고 HTML 5 비디오 요소라면 아마도 운이 없을 것입니다. Firefox 64.0은 범위 요청을 통해 서비스를 제공하는지 여부에 관계없이 이러한 스크러빙 가능하게 만들려고 노력하지만, 적절하다고 생각하는 것보다 몇 배 더 많이 검색하면 스트림이 완전히 다운로드 될 때까지 혼란스럽고 회전하는 바퀴를 던집니다. 크롬은 시도조차하지 않고, 그냥 나오지 않고 전체 스트림 재생 이 끝날 때까지 스크럽을 전혀 허용하지 않습니다 .


다음은 이러한 종류의 파일을 지원하는 것에 대해 이야기하는 FF 개발자의 긴 스레드입니다. bugzilla.mozilla.org/show_bug.cgi?id=657791
Chris McDonough
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.