Cabeçalho do intervalo de HTTP

Eu estava lendo http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 e tentando descobrir como continuar com o download de um arquivo.

Por exemplo, suponha que um arquivo tenha 100 bytes de comprimento e eu tenha todos os 100 bytes. No entanto, não sei qual deve ser o tamanho esperado do arquivo, por isso peço o arquivo e especifique um header Range que se pareça com isto:

Range: bytes=100- 

Esta é uma solicitação de intervalo válida?

É uma solicitação sintaticamente válida, mas não uma solicitação satisfatória. Se você olhar mais adiante nessa seção, verá:

Se um conjunto de intervalos de bytes sintaticamente válido include pelo menos uma especificação de intervalo de bytes cuja primeira posição de byte é menor que o comprimento atual do corpo da entidade, ou pelo menos uma especificação de intervalo de bytes de sufixo com um não – comprimento do sufixo zero, então o conjunto de intervalos de bytes é satisfatível. Caso contrário, o conjunto de intervalos de bytes é insatisfatório. Se o conjunto de intervalo de bytes for insatisfável, o servidor deve retornar uma resposta com um status de 416 (intervalo solicitado não satisfazível) . Caso contrário, o servidor DEVE retornar uma resposta com um status de 206 (Conteúdo Parcial) contendo os intervalos satisfatórios do corpo da entidade.

Então, eu acho que no seu exemplo, o servidor deve retornar um 416, pois não é um intervalo de bytes válido para esse arquivo.

Como Wrikken sugeriu, é um pedido válido. Também é bastante comum quando o cliente está solicitando mídia ou retomando um download.

Um cliente geralmente testa para ver se o servidor lida com solicitações à distância, além de procurar por uma resposta de Accept-Ranges . O Chrome sempre envia um Range: bytes=0- com sua primeira solicitação GET para um vídeo, então é algo que você não pode ignorar.

Sempre que um cliente inclui Range: em sua solicitação, mesmo que esteja malformado, ele está esperando uma resposta de conteúdo parcial (206). Quando você procura para frente durante a reprodução de vídeo HTML5, o navegador só solicita o ponto de partida. Por exemplo:

 Range: bytes=3744- 

Portanto, para que o cliente reproduza o vídeo corretamente, seu servidor deve ser capaz de lidar com essas solicitações de intervalo incompletas.

Você pode manipular o tipo de ‘intervalo’ especificado em sua pergunta de duas maneiras:

Primeiro, você pode responder com o ponto de partida solicitado na resposta e, em seguida, o comprimento total do arquivo menos um (o intervalo de bytes solicitado é indexado com zero). Por exemplo:

Pedido:

 GET /BigBuckBunny_320x180.mp4 Range: bytes=100- 

Resposta:

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

Em segundo lugar, você poderia responder com o ponto de partida dado na solicitação e um comprimento de arquivo em aberto (tamanho). Isso é para webcasts ou outras mídias em que o tamanho total é desconhecido. Por exemplo:

Pedido:

 GET /BigBuckBunny_320x180.mp4 Range: bytes=100- 

Resposta:

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

Dicas:

Você deve sempre responder com o comprimento do conteúdo incluído no intervalo. Se o intervalo estiver completo, com o início até o fim, o tamanho do conteúdo será simplesmente a diferença:

Pedido: intervalo: bytes = 500-1000

Resposta: intervalo de conteúdo: bytes 500-1000 / 123456

Lembre-se que o intervalo é indexado em zero, então Range: bytes=0-999 está realmente solicitando 1000 bytes, não 999, então responda com algo como:

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

Ou:

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

Mas, evite o último método, se possível, porque alguns players de mídia tentam descobrir a duração do tamanho do arquivo. Se a sua solicitação for para conteúdo de mídia, que é meu palpite, inclua sua duração na resposta. Isso é feito com o seguinte formato:

 X-Content-Duration: 63.23 

Este deve ser um ponto flutuante. Ao contrário do Content-Length , esse valor não precisa ser preciso. É usado para ajudar o jogador a procurar o vídeo. Se você estiver transmitindo um webcast e só tiver uma ideia geral de quanto tempo será, é melhor include sua duração estimada em vez de ignorá-la completamente. Então, para um webcast de duas horas, você pode include algo como:

 X-Content-Duration: 7200.00 

Com alguns tipos de mídia, como o webm, você também deve include o tipo de conteúdo, como:

 Content-Type: video/webm 

Tudo isso é necessário para que a mídia seja reproduzida corretamente, especialmente no HTML5. Se você não der uma duração, o jogador pode tentar descobrir a duração (para permitir a busca) do tamanho do arquivo, mas isso não será exato. Isso é bom e necessário para webcasts ou transmissão ao vivo, mas não é ideal para a reprodução de arquivos de vídeo. Você pode extrair a duração usando um software como o FFMPEG e salvá-lo em um database ou até mesmo no nome do arquivo.

X-Content-Duration está sendo eliminada em favor da Content-Duration , então incluí isso também. Uma resposta básica a uma solicitação “0-” includeia pelo menos o seguinte:

 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 

Mais um ponto: o Chrome sempre inicia sua primeira solicitação de vídeo com o seguinte:

 Range: bytes=0- 

Alguns servidores enviarão uma resposta 200 normal como uma resposta, que aceita (mas com opções limitadas de reprodução), mas tente enviar um 206 em vez de mostrar do que o seu servidor manipula os intervalos. A RFC 2616 diz que é aceitável ignorar headers de alcance.

Ao contrário da resposta de Mark Novakowski, que por algum motivo foi votada por muitos, sim, é um pedido válido e satisfatório.

Na verdade, o padrão, como Wrikken apontou, faz exatamente um exemplo. Na prática, o Firefox responde a essas solicitações conforme o esperado (com um código 206), e é exatamente isso que eu uso para implementar o download progressivo, ou seja, obter apenas a cauda de um arquivo de log longo que cresce em tempo real com as pesquisas.