También disponible en: English · Português · Français · العربية
Peticiones de rango HTTP: qué pide una cabecera Range y qué vuelve
Escribe una cabecera Range y un tamaño de archivo, y mira los bytes exactos, el código de estado y el Content-Range que mandaría un servidor conforme.
Qué es una petición de rango HTTP
Una petición de rango pide al servidor una parte de un archivo en vez del archivo entero. Es como un reproductor de vídeo salta al minuto veinte sin descargar los diecinueve anteriores, como se reanuda una descarga que se cortó, y como un visor de PDF pinta la página 400 de un documento grande sin traerse las 399 primeras. El cliente manda una cabecera Range con los desplazamientos de byte que quiere; el servidor que accede responde 206 Partial Content con esos bytes y una cabecera Content-Range diciendo cuáles eran.
La sintaxis es una unidad de rango, un igual, y uno o más rangos separados por comas. Solo hay una unidad definida —bytes— y los desplazamientos son inclusivos y empiezan en cero, así que bytes=0-499 son los primeros quinientos bytes y bytes=500-999 los quinientos siguientes. El desplazamiento final se puede omitir, y entonces significa todo desde ahí hasta el final.
La forma que despista es la que no lleva nada antes del guion. bytes=-500 no es un error ni un desplazamiento de menos quinientos: la especificación lo llama rango de sufijo y lo define, con sus palabras, como las últimas N unidades del recurso. Así que pide los quinientos bytes finales, y bytes=0-0,-1 pide el primer byte y el último, que es el ejemplo de la propia especificación.
Cómo usarlo
- Escribe una cabecera Range y un tamaño de archivo. La cabecera va tal cual la mandarías, con espacios tras las comas o sin ellos: los ejemplos de la especificación los llevan. El tamaño es la longitud del archivo entero, porque todos los desplazamientos se calculan sobre ella.
- Lee la fila del estado. 206 significa que se atendieron los rangos y 416 que no se pudo atender ninguno, y la herramienta enseña el Content-Range que llevaría cada respuesta. Los botones de ejemplo cubren un rango de sufijo, uno normal, una petición de dos partes y otra que cae más allá del final.
- Mira la tabla. Enumera el primer y el último byte exactos de cada parte que llegaría, su tamaño, y el Content-Range que lleva esa parte. Debajo, los hallazgos explican lo que la especificación diga de lo que has pedido.
El servidor tiene permiso para ignorarte
Esto es lo primero que conviene interiorizar, y está dicho sin rodeos: un servidor puede ignorar la cabecera Range. No rechazarla, no dar error: ignorarla, y contestar 200 con el archivo entero como si nunca se hubiera mandado. Esa es una respuesta conforme, así que cualquier cliente que pida rangos tiene que saber recibir un cuerpo completo en vez de uno parcial.
La especificación insiste desde el otro lado al hablar del 416: como los servidores son libres de ignorar Range, muchas implementaciones responden con el recurso entero en un 200, de donde concluye que los clientes no pueden contar con recibir un 416 ni siquiera cuando es lo más apropiado. Si tu lógica de reanudación trata cualquier cosa que no sea 206 como un fallo, se romperá contra un servidor perfectamente conforme.
El alcance es además más estrecho de lo que casi todo el mundo supone. El manejo de rangos está definido para exactamente un método: un servidor debe ignorar una cabecera Range en una petición cuyo método no reconozca o para el que no haya manejo de rangos definido, y GET es el único método para el que la especificación lo define. Un Range en un POST está obligado a no hacer nada.
Un rango y dos rangos son respuestas distintas
Pide un solo rango y obtienes un 206 con ese rango como cuerpo y una cabecera Content-Range arriba diciendo qué bytes son y sobre qué total. Pide dos y la forma cambia por completo: el servidor debe mandar contenido multipart/byteranges, con un parámetro boundary en el Content-Type, y cada rango llega como su propia parte con sus propias cabeceras.
Y aquí está la regla que sorprende a casi todo el mundo, y es un MUST NOT y no una cuestión de gusto: un servidor no debe poner una cabecera Content-Range en la sección de cabeceras de una respuesta de varias partes, porque ese campo va dentro de cada parte. El código que lee Content-Range de la respuesta para saber qué le ha llegado no leerá nada en cuanto se añada un segundo rango. La prohibición va también al revés: un servidor no debe envolver un solo rango en formato multiparte, porque un cliente que pidió una parte podría no saber leer multiparte.
Antes de mandar una lista larga conviene conocer dos permisos más. Un servidor puede fusionar rangos que se solapen, o que estén separados por un hueco menor que el coste de mandarlos aparte, y puede hacerlo sin respetar el orden en que aparecieron en tu cabecera: lo que vuelve no tiene por qué coincidir con lo que pediste, ni en número ni en secuencia. Y el formato no sale gratis: la especificación cifra la sobrecarga entre partes en unos ochenta bytes, y observa que transferir muchas partes pequeñas y disjuntas puede ser menos eficiente que transferir el recurso entero. La herramienta te suma eso y te avisa cuando pasa.
Lo que esto no te va a decir
Esto averigua qué significa una cabecera. No habla con tu servidor. Un navegador no puede hacer una petición a otro origen y leerte las cabeceras de respuesta sin la cooperación de ese servidor, así que aquí no se descarga nada: el tamaño del archivo es el número que escribiste, no uno medido. Para ver qué hace un servidor de verdad, usa el panel de red del navegador o una petición desde la línea de comandos con la cabecera puesta a mano.
Tampoco puede decirte si el servidor admite rangos. Eso se anuncia con una cabecera Accept-Ranges en una respuesta normal, y como un servidor puede ignorar Range de todos modos, la única respuesta segura es pedir un rango y ver qué vuelve. Un 206 significa que sí; un 200 significa o que no, o que sí pero esta vez no.
Hay una simplificación en la aritmética. Los desplazamientos de byte en HTTP no tienen tope, y la especificación avisa expresamente de que hay que anticipar numerales decimales potencialmente enormes y evitar errores por desbordamiento de enteros. Esta página trabaja con números normales de JavaScript, exactos hasta unos nueve billones largos: mucho más que cualquier archivo real, pero no infinito, así que un desplazamiento absurdamente grande perderá precisión aquí de un modo en que un servidor cuidadoso no la perdería.
Por último, las peticiones de rango condicionales quedan fuera. Una reanudación de verdad suele acompañar Range de If-Range para que el servidor compruebe que el archivo no ha cambiado por debajo y mande el entero si lo ha hecho. Esa interacción es un mecanismo aparte con sus propias reglas, y esta página solo responde a qué bytes nombra un Range dado.
¿Por qué es gratis?
Analizar una cabecera y hacer aritmética con desplazamientos de byte corre en tu navegador. No hay ningún servidor de por medio, así que no hay nada que cobrar ni cuenta que crear.
No se sube nada y no se descarga nada. Recarga la página y habrá olvidado lo que escribiste.