Também disponível em: English · Español · Français · العربية
Requisições de intervalo HTTP: o que um cabeçalho Range pede, e o que volta
Digite um cabeçalho Range e um tamanho de arquivo, e veja os bytes exatos, o código de status e o Content-Range que um servidor conforme mandaria.
O que é uma requisição de intervalo HTTP
Uma requisição de intervalo pede ao servidor parte de um arquivo em vez do arquivo inteiro. É assim que um player de vídeo pula para o minuto vinte sem baixar os dezenove anteriores, que um download retoma depois de cair, e que um leitor de PDF desenha a página 400 de um documento grande sem buscar as 399 primeiras. O cliente manda um cabeçalho Range com os deslocamentos de byte que quer; o servidor que atende responde 206 Partial Content com esses bytes e um cabeçalho Content-Range dizendo quais eram.
A sintaxe é uma unidade de intervalo, um sinal de igual, e um ou mais intervalos separados por vírgulas. Só existe uma unidade definida — bytes — e os deslocamentos são inclusivos e começam em zero, então bytes=0-499 são os primeiros quinhentos bytes e bytes=500-999 os quinhentos seguintes. O deslocamento final pode ser omitido, e aí significa tudo dali até o fim.
A forma que confunde é a que não tem nada antes do hífen. bytes=-500 não é um erro nem um deslocamento de menos quinhentos: a especificação chama isso de intervalo de sufixo e define, com as próprias palavras, como as últimas N unidades do recurso. Ou seja, pede os quinhentos bytes finais, e bytes=0-0,-1 pede o primeiro byte e o último, que é o exemplo da própria especificação.
Como usar
- Digite um cabeçalho Range e um tamanho de arquivo. O cabeçalho entra como você o mandaria, com ou sem espaços depois das vírgulas — os exemplos da especificação têm espaços. O tamanho é o comprimento do arquivo inteiro, porque todos os deslocamentos são calculados sobre ele.
- Leia a linha do status. 206 significa que os intervalos foram atendidos e 416 que nenhum pôde ser, e a ferramenta mostra o Content-Range que cada resposta carregaria. Os botões de exemplo cobrem um intervalo de sufixo, um comum, uma requisição de duas partes e outra que cai além do fim.
- Olhe a tabela. Ela lista o primeiro e o último byte exatos de cada parte que chegaria, o tamanho dela, e o Content-Range que aquela parte carrega. Abaixo, os achados explicam o que a especificação diz sobre o que você pediu.
O servidor tem permissão para te ignorar
Esta é a primeira coisa que vale internalizar, e está dita sem rodeios: um servidor pode ignorar o cabeçalho Range. Não rejeitar, não dar erro — ignorar, e responder 200 com o arquivo inteiro como se o cabeçalho nunca tivesse sido mandado. Essa é uma resposta conforme, então qualquer cliente que peça intervalos precisa saber receber um corpo completo em vez de um parcial.
A especificação insiste pelo outro lado ao tratar do 416: como os servidores são livres para ignorar Range, muitas implementações respondem com o recurso inteiro num 200, e daí conclui que os clientes não podem contar com receber um 416 nem quando ele é o mais apropriado. Se a sua lógica de retomada trata qualquer coisa que não seja 206 como falha, ela vai quebrar contra um servidor perfeitamente conforme.
O escopo também é mais estreito do que quase todo mundo supõe. O tratamento de intervalos é definido para exatamente um método: um servidor deve ignorar um cabeçalho Range numa requisição cujo método ele não reconheça ou para o qual não haja tratamento de intervalos definido, e GET é o único método para o qual a especificação define isso. Um Range num POST é obrigado a não fazer nada.
Um intervalo e dois intervalos são respostas diferentes
Peça um único intervalo e você recebe 206 com aquele intervalo como corpo e um cabeçalho Content-Range no topo dizendo quais bytes e sobre qual total. Peça dois e o formato muda por completo: o servidor precisa mandar conteúdo multipart/byteranges, com um parâmetro boundary no Content-Type, e cada intervalo chega como uma parte própria com cabeçalhos próprios.
E aqui está a regra que surpreende quase todo mundo, e é um MUST NOT e não uma questão de gosto: um servidor não deve pôr um cabeçalho Content-Range na seção de cabeçalhos de uma resposta de várias partes, porque esse campo vai dentro de cada parte. O código que lê Content-Range da resposta para saber o que chegou não vai ler nada no momento em que um segundo intervalo for acrescentado. A proibição vale ao contrário também: um servidor não deve embrulhar um único intervalo em formato multiparte, porque um cliente que pediu uma parte pode não saber ler multiparte.
Antes de mandar uma lista longa vale conhecer mais duas permissões. Um servidor pode fundir intervalos que se sobreponham, ou que estejam separados por um vão menor que o custo de mandá-los à parte, e pode fazer isso sem respeitar a ordem em que apareceram no seu cabeçalho — então o que volta não precisa bater com o que você pediu, nem em quantidade nem em sequência. E o formato não sai de graça: a especificação estima o custo entre partes em cerca de oitenta bytes, e observa que transferir muitas partes pequenas e disjuntas pode ser menos eficiente que transferir o recurso inteiro. A ferramenta soma isso para você e avisa quando acontece.
O que isto não vai te dizer
Isto descobre o que um cabeçalho significa. Não conversa com o seu servidor. Um navegador não consegue fazer uma requisição para outra origem e ler os cabeçalhos de resposta sem a cooperação daquele servidor, então nada aqui é baixado: o tamanho do arquivo é o número que você digitou, não um medido. Para ver o que um servidor real faz, use o painel de rede do navegador ou uma requisição pela linha de comando com o cabeçalho posto à mão.
Também não dá para dizer se o servidor suporta intervalos. Isso é anunciado com um cabeçalho Accept-Ranges numa resposta comum, e como um servidor pode ignorar Range de qualquer jeito, a única resposta certa é pedir um intervalo e ver o que volta. Um 206 quer dizer que sim; um 200 quer dizer ou que não, ou que sim mas não desta vez.
Há uma simplificação na aritmética. Deslocamentos de byte no HTTP não têm teto, e a especificação avisa explicitamente que é preciso antecipar numerais decimais potencialmente enormes e evitar erros por estouro de inteiros. Esta página trabalha com números normais de JavaScript, exatos até cerca de nove quatrilhões — muito além de qualquer arquivo real, mas não ilimitado, então um deslocamento absurdamente grande vai perder precisão aqui de um jeito que um servidor cuidadoso não perderia.
Por fim, requisições de intervalo condicionais ficam de fora. Uma retomada de verdade normalmente acompanha o Range com um If-Range para o servidor conferir que o arquivo não mudou por baixo e mandar o inteiro se mudou. Essa interação é um mecanismo à parte com regras próprias, e esta página responde só a qual conjunto de bytes um dado Range nomeia.
Por que é grátis?
Analisar um cabeçalho e fazer aritmética com deslocamentos de byte roda no seu navegador. Não há servidor envolvido, então não há nada para cobrar nem conta para criar.
Nada é enviado e nada é baixado. Recarregue a página e ela terá esquecido o que você digitou.