Prompt y contexto
Esta pregunta de backend evalúa respuestas parciales HTTP, lecturas en almacenes de objetos (object-store) y una máquina de estados de descarga. El desafío no radica en reenviar un encabezado al almacenamiento; consiste en mantener consistentes los rangos, las versiones de la entidad, las codificaciones, los permisos y los segmentos concurrentes ante fallas y reintentos.
Qué evalúa el entrevistador
- Si parseas un rango de bytes y construyes 206, Content-Range, Content-Length y Accept-Ranges correctamente.
- Si ETag o Last-Modified junto con If-Range evitan que un cliente una distintas versiones de un archivo.
- Si se manejan rangos inválidos, firmas expiradas, objetos eliminados, límites de tasa (rate limits) y el costo de rangos múltiples (multi-range).
- Si la integridad, la observabilidad y la autorización evitan que el endpoint se convierta en un lector arbitrario de objetos.
Preguntas de clarificación para hacer
Confirma si los objetos son públicos, el tamaño máximo, si se requieren respuestas de rangos múltiples, si el almacenamiento soporta rangos nativos, si se permite la compresión y si el cliente persiste los ETags. Pregunta sobre el tiempo de vida de la URL, la concurrencia de segmentos, el algoritmo de integridad y el comportamiento del producto cuando cambia la versión del recurso.
Estructura de respuesta en 30 segundos
Autorizaría la solicitud y fijaría una versión del objeto, para luego leer el tamaño, el ETag y los metadatos de medios. Sin Range se devuelve 200; un rango satisfacible devuelve 206 con un Content-Range exacto; rangos malformados o no satisfacibles devuelven 416 con la longitud actual. Una discrepancia en If-Range causa una respuesta completa para la versión actual de modo que el cliente reinicie. Cada segmento tiene límites de tasa y de concurrencia, y tanto la respuesta como el archivo final se verifican contra la versión y la suma de comprobación (checksum).
Análisis paso a paso en profundidad
1. Fijar la representación y el límite de autorización
Autoriza por usuario, tenant e identificador de objeto; nunca mapees una ruta arbitraria del cliente directamente a una clave de almacenamiento. Lee los metadatos del objeto y fija un identificador de versión, los bytes totales, Content-Type, Content-Encoding y el ETag. Si los objetos cambian, utiliza almacenamiento inmutable o versionado para que los metadatos y los bytes no diverjan durante una descarga.
2. Parsear rangos y construir respuestas
Soporta un rango bytes=start-end, bytes=start- o bytes=-suffix, validando enteros, desbordamiento (overflow) y la longitud total. Después de ajustar un rango satisfacible a la representación, devuelve 206, Content-Range y la longitud exacta. Sin Range, devuelve 200. Si ningún rango es satisfacible, devuelve 416 con Content-Range: bytes */total. Las solicitudes de rangos múltiples necesitan una decisión explícita: rechazar, dividir en solicitudes acotadas o implementar multipart; nunca devuelvas silenciosamente la primera parte.
3. Manejar If-Range y codificación de contenido
Respeta un ETag fuerte o una fecha en If-Range solo cuando aún coincida con la representación seleccionada; de lo contrario, ignora Range y envía la representación actual completa. Los rangos se refieren a los bytes de la representación realmente transferida. No recortes bytes comprimidos pidiendo al cliente que los una como si fueran un archivo sin comprimir. Deshabilita la compresión dinámica o asigna a cada codificación una versión y checksum independientes.
4. Acotar concurrencia, costo y recuperación
Limita los segmentos por usuario, tenant y objeto, además del ancho de banda total y el tamaño mínimo de rango, para evitar que muchas solicitudes diminutas amplifiquen el costo de almacenamiento. Reintenta un segmento fallido únicamente con la misma versión y rango. Si una URL firmada expira, emite una nueva sin cambiar la versión. La eliminación del objeto o los cambios de permisos detienen los segmentos posteriores, y el cliente descarta un archivo incompleto en lugar de unirlo silenciosamente.
5. Verificar integridad y observar el comportamiento
Después de la descarga, verifica la versión del objeto, la longitud total y el checksum; para datos de alto riesgo, verifica cada segmento antes de unirlo. Registra rangos normalizados, versión, estado, bytes, latencia de almacenamiento, acierto de caché (cache hit) y recuento de reintentos sin registrar credenciales de descarga. Prueba rangos vacíos, sufijos, desbordamientos, actualizaciones de objetos, reintentos concurrentes, reanudación sin conexión y cada Content-Encoding para demostrar que 206 nunca sirva la versión incorrecta.
Respuesta de ejemplo sólida
Tras la autorización, fijo una versión inmutable del objeto y expongo su tamaño, ETag, tipo y codificación. Un único rango bytes satisfacible devuelve 206 con Content-Range y Content-Length; la ausencia de rango devuelve 200; uno no satisfacible devuelve 416 con bytes */total. La discrepancia en If-Range ignora Range y envía la versión actual completa, evitando archivos mezclados. Los límites de concurrencia, tasa y rango mínimo por usuario y por objeto contienen los costos, y los reintentos mantienen la misma versión. El cliente verifica la longitud, la versión y el checksum; el servidor observa rangos, estado, latencia de almacenamiento y reintentos.
Errores comunes
- Reenviar Range sin verificar autorización, versión del objeto o desbordamiento de enteros.
- Devolver 200 o un cuerpo vacío para un rango no satisfacible en lugar de 416.
- Ignorar If-Range y permitir que una actualización cree un archivo con versiones mezcladas.
- Aplicar coordenadas de rango a bytes comprimidos que el cliente luego trata como no comprimidos.
- Permitir segmentos diminutos y concurrencia ilimitados, convirtiendo una sola descarga en una tormenta de solicitudes al almacenamiento.
- Verificar únicamente los códigos de estado en lugar de la longitud total, el ETag y el checksum final.
Preguntas de seguimiento y respuestas
¿Por qué no devolver siempre 206?
Sin Range el cliente solicitó la representación completa, por lo que 200 es correcto. Incluso con Range, el servidor debe comprobar la satisfacibilidad; 416 indica al cliente la longitud actual para que pueda corregir la solicitud.
¿En qué se diferencia If-Range de If-Match?
If-Range decide si la transferencia parcial puede continuar: una coincidencia produce 206 y una discrepancia produce la representación completa. If-Match es una precondición para ejecutar una operación de destino, por lo que su fallo tiene un significado diferente.
¿Qué se debe hacer con las solicitudes de rangos múltiples?
Primero confirma que el cliente y el almacenamiento las necesiten. Divídelas en solicitudes acotadas o implementa multipart/byteranges; si el costo no está justificado, rechaza explícitamente en lugar de devolver el primer rango y crear ambigüedad.
¿Cómo evitas que los enlaces de descarga firmados sean objeto de abuso?
Utiliza firmas de corta duración vinculadas a usuario, tenant, objeto, versión y permiso. Vuelve a verificar los límites en el lado del servidor y limita la concurrencia, la tasa, el recuento de rangos y los bytes totales. El acceso revocado o la eliminación deben invalidar las solicitudes de rango subsiguientes.