http

HTTP herramientas

Una referencia práctica para depurar HTTP: semántica de estados y redirecciones, directivas de Cache-Control, y a qué herramienta recurrir cuando los encabezados, las URL o las tarjetas de compartición se portan mal.

9 herramientas

§01 GUÍA DEL TEMA

Qué estás depurando en realidad

Un intercambio HTTP son cuatro cosas separables, y la mayor parte del tiempo de depuración que se pierde viene de confundirlas: la URL (lo que pediste), los encabezados de petición (quién dices ser y qué aceptas), la línea de estado (el veredicto) y los encabezados de respuesta (el contrato de caché, seguridad y tipo de contenido). El cuerpo es la parte menos interesante: cuando está mal, los encabezados ya han explicado por qué.

En segundo lugar, casi nada de lo que te muestra un navegador es la salida en bruto del origen. Entre tu servidor y el panel Network se interponen un CDN, quizá un proxy, HTTP/2 o /3 (que pasan a minúsculas los nombres de campo y descartan la frase de motivo), un service worker y la caché de disco. Una fila 200 OK (from disk cache) es el recuerdo de una respuesta, no una respuesta, así que cuando un encabezado parezca faltar, pregúntate primero de quién es la copia que estás leyendo.

En tercer lugar, HTTP es en gran medida autodeclarado: User-Agent, Referer, Accept-Language y todos los encabezados personalizados X- son afirmaciones que un cliente eligió enviar, falsificables en una línea de código. Solo lo que emite el origen — el código de estado y los encabezados de respuesta — está bajo tu control.

Las clases de estado de un vistazo

ClaseSignificadoQué debería hacer el clienteCacheable por heurística
1xxProvisional (100, 101, 103)Seguir esperandoNo
2xxÉxitoUsar el cuerpo (204 no tiene)200, 203, 204, 206
3xxRedirección / revalidaciónSeguir Location; reutilizar la caché en 304300, 301, 308
4xxMal tal como se envióCorregirlo; no reintentar a ciegas404, 405, 410, 414
5xxEl servidor falló con una petición válidaReducir el ritmo; respetar Retry-AfterSolo 501

Dos códigos se manejan mal de forma habitual: 429 debería llevar Retry-After, y 304 Not Modified es un éxito: registrarlo como error oculta una caché que funciona.

La matriz de redirecciones que la gente confunde

CódigoPermanenciaMétodo y cuerpo conservadosUsar para
301PermanenteNo — puede pasar a GETURL renombrada, consolidación de hosts
302TemporalNo — mismo riesgo de reescrituraValor histórico por defecto; evitar con POST
303TemporalNo — fuerza GETPOST y después redirección a un resultado
307TemporalTraslado temporal de un endpoint de API
308PermanenteTraslado permanente de un endpoint POST

Los navegadores además guardan los 301 con fuerza, a veces durante toda la vida del perfil, así que un 301 equivocado es caro de deshacer: verifícalo primero en preproducción.

Cache-Control, directiva por directiva

DirectivaGobiernaNota
max-age=NFrescura en segundos, en cualquier caché0 fuerza la revalidación
s-maxage=NFrescura solo para las cachés compartidasPrevalece sobre max-age en el CDN
no-cacheGuardar sí; revalidar antes de reutilizarNo es no-store
no-storeProhíbe guardar la respuestaHTML autenticado
privateEl navegador puede guardar, las cachés compartidas noRespuestas personalizadas
must-revalidateSin servir contenido obsoleto en caso de errorCombinar con max-age
immutableNo revalidar nunca mientras esté frescoRecursos con hash en el nombre
stale-while-revalidate=NServir obsoleto y refrescar en segundo planoSuaviza los fallos de caché del CDN

Vary también pertenece a esta lista: si una respuesta cambia según Accept-Language o un encabezado personalizado y nunca lo declaras, una caché compartida entregará la variante equivocada a la siguiente visita.

Qué herramienta para cada pregunta

Cuando tienes una URL y quieres la respuesta propia del origen, usa Cabeceras HTTP: la petición sale de api.sitekits.dev, así que no hay ninguna extensión, caché ni service worker en el camino, y obtienes el estado final, la URL final, el número de saltos y todos los encabezados de respuesta. Solo lee encabezados, nunca el cuerpo, y su protección SSRF rechaza localhost y los rangos privados.

Cuando necesitas enviar algo concreto — un PATCH con cuerpo JSON, un encabezado Authorization: Bearer, un OPTIONS a secas para leer una comprobación previa — usa el Probador REST API. Las peticiones van desde tu navegador directas al destino, así que su política CORS se aplica igual que al código de tu propio frontend: ideal cuando el error es el CORS. Si el token es el sospechoso, pégalo en el Decodificador JWT para leer exp y las reclamaciones; descodificar no es verificar.

Cuando la unidad que falla es una carga de página completa y no una petición sola, exporta un HAR al Visor HAR; la guía de campo de HAR cubre los tiempos. Los misterios de la cadena de consulta caen ante el Parseador de URL, que lista los parámetros descodificados del formato porcentual mediante el analizador WHATWG del navegador, más URL Encode cuando un valor se escapó una vez de más. El Parseador UserAgent reduce una cadena UA a navegador, sistema operativo, clase de dispositivo y una heurística de bot; los códigos que no reconoces van a los Códigos HTTP; y un archivo que se descarga en lugar de mostrarse suele ser una cuestión de Content-Type para el Verificador MIME. Cuando la respuesta está sana pero la tarjeta de compartición sale mal, pega el HTML de la página en la Vista Previa OG: el análisis es local, así que funciona con compilaciones de preproducción y detrás de un inicio de sesión.

Trampas

Strict-Transport-Security en una respuesta HTTP no hace nada

Los navegadores ignoran el HSTS entregado por HTTP sin cifrar, y las cookies Secure también se descartan ahí. Sirve la redirección de actualización en el puerto 80 y los encabezados de seguridad en la respuesta HTTPS, y comprueba los dos saltos, no solo el último.

Los encabezados de seguridad son por respuesta, no por sitio

Un Content-Security-Policy endurecido en tu HTML no dice nada del JSON de tu API, de las páginas de error de tu CDN ni de un bucket de subidas que esté en otra parte. El Generador CSP escribe el encabezado; es tu configuración de despliegue la que decide qué respuestas lo llevan.

Las cadenas de redirecciones cuestan idas y vueltas

http://example.comhttps://example.comhttps://www.example.com//home/ cuesta tres idas y vueltas extra antes de cualquier HTML, y cada salto puede descartar un método, una cookie o una cadena de consulta. Redúcela a un solo salto en el borde.

Un 200 con un error en el cuerpo derrota a la monitorización por estado

Responder 200 mientras la carga útil dice {"error": ...} oculta los fallos a las alertas basadas en la clase de estado e infla la disponibilidad medida. Si el SLO es tuyo, comprueba también la carga útil; mira las herramientas reunidas para el trabajo de SRE.

+ y %20 no son intercambiables

En una cadena de consulta codificada como application/x-www-form-urlencoded, + se descodifica como espacio; en un segmento de ruta es un signo más literal. La doble codificación es el error hermano: %20 pasa a %2520 y la rotura parece de enrutamiento, no de escapado.

FAQ
¿Por qué mi POST se convirtió en GET después de una redirección?
Porque 301 y 302 permiten que los clientes reescriban el método a GET y descarten el cuerpo, y los navegadores hacen exactamente eso. Usa 307 para un traslado temporal y 308 para uno permanente cuando el método y el cuerpo deban sobrevivir al salto. Un formulario o un webhook que pierde su carga útil en silencio suele estar topándose con una redirección de http a https o de barra final configurada como 301.
¿Por qué los encabezados de respuesta en DevTools difieren de lo que dice la configuración de mi servidor?
Lo que muestra DevTools es la respuesta después de todos los saltos. Un CDN, un proxy inverso o un service worker pueden añadir, reescribir o quitar encabezados, HTTP/2 y /3 pasan a minúsculas todos los nombres de campo y descartan la frase de motivo, y una fila marcada como 200 (from disk cache) no es en absoluto una respuesta fresca. Solicitar la URL desde el servidor elimina esas variables y muestra qué emitió el origen para la URL final de la cadena.
¿Cache-Control no-cache impide que los navegadores guarden mi página?
No. no-cache permite guardarla pero exige revalidar con el origen, normalmente mediante ETag e If-None-Match, antes de reutilizar una copia guardada. no-store es la directiva que prohíbe escribir la respuesta en disco. El HTML autenticado suele querer private, no-store, mientras que los recursos estáticos con hash en el nombre quieren un max-age largo más immutable.
¿Por qué mi API funciona con curl pero falla en el navegador con un error de CORS?
El CORS lo aplica el navegador, no el servidor, y curl lo ignora por completo. Para cualquier cosa que vaya más allá de una petición simple, el navegador envía primero una comprobación previa OPTIONS, y se niega a exponer la respuesta salvo que el origen devuelva un Access-Control-Allow-Origin que coincida, más Access-Control-Allow-Credentials cuando hay cookies implicadas. El servidor a menudo responde 200 perfectamente; simplemente no puedes leerlo. Inspecciona primero la respuesta al OPTIONS.
¿Por qué se ignora mi encabezado Strict-Transport-Security?
Porque los navegadores solo respetan HSTS cuando llega por HTTPS. Una política servida en una respuesta de HTTP sin cifrar se descarta sin más — igual que cualquier cookie Secure que se fije ahí — así que la respuesta del puerto 80 debería llevar la redirección de actualización y nada más, con los encabezados de seguridad adjuntos a la respuesta HTTPS. Comprueba cada salto en lugar del 200 final: un encabezado presente al final de una cadena de redirecciones no dice nada sobre lo que envió el primer salto. Recuerda que includeSubDomains y preload comprometen todos los subdominios a HTTPS durante el max-age que publicaste, y que salir de la lista de preload tarda meses.