
Hace unas semanas convertí este blog en una web headless: WordPress se quedó como el panel donde escribo y Astro, alojada en Cloudflare, se encarga de lo que ves. Todo iba bien hasta que, de cuando en cuando, la publicación empezó a fallar sin que yo hubiera tocado nada. En mi navegador todo funcionaba. En el servidor de compilación, no.
Vamos que cuando Cloudflare automatizaba la subida por error….
La respuesta corta: si tu web headless falla porque WordPress devuelve HTML en lugar de JSON, casi seguro no es un error de tu código. Entre tu proceso y el CMS hay algo (una protección anti-bots, una redirección, una página de mantenimiento) que contesta con una página pensada para personas y no para programas.
Qué pasa cuando WordPress devuelve HTML en lugar de datos
Una web headless funciona así: al compilar, mi proyecto le pide a WordPress la lista de artículos y espera recibirla como JSON, un formato de datos que cualquier programa entiende. Yo esperaba datos y llegaba una página web, bueno un HTML.
Lo más liaba el asunto es que la respuesta venia de la mano de un código 200, que significa «todo correcto, todo ok, tranqui». Para el servidor, no había ningún problema. El problema estaba en lo que contenía: texto de una página, no datos y recordemos que JSON sirve para almacenar, organizar y intercambiar datos de forma ligera. Mi primer mensaje de error solo decía «respuesta inesperada», y con eso no hay manera de saber qué ha pasado.
Por qué en mi navegador funcionaba y en el build no
Cuando abría la dirección de los datos en el navegador, veía el JSON perfectamente. Un navegador ejecuta JavaScript, guarda cookies y se comporta como una persona. Mi proceso de compilación no: pide la dirección, lee lo que llega y se va, sin mirar atras.
Ahí estaba la diferencia. La página que recibía mi build era una pantalla de «un momento, por favor» que se recargaba sola a los pocos segundos: el equivalente a que el portero te diga «espere ahí un momento» y se vaya a por un café. Un navegador espera con educación, sonríe, la supera y entra. Mi programa, sin JavaScript, se queda mirando la puerta, lee el cartel de «espere» y concluye: «Vale, esto es lo que había que traer». Y se vuelve a casa con el cartel…..en lugar de los datos.
Para colmo, fallaba a ratos. Unas veces la publicación terminaba bien y otras no, porque el portero decide según quién llama y desde dónde. Con unos visitantes se hace el simpático, y con otros me ponía a hacer cola. Lo llamé «intermitente», pero teniamos al «portero con cambios de humor».
Cómo descubrí que WordPress devolvía HTML
Asi que me sente delante del pc, con mis gafas y bata blanca estilo CSI y hasta me puse «The Who», pero habia que saber o descubir el error y que lo causaba…
Asi que cambie el codigo para que si la respuesta no es JSON, se meustre el tipo de contenido y las primeras lineas,
const res = await fetch(url);
const tipo = res.headers.get('content-type') || '';
if (!res.ok || !tipo.includes('json')) {
const cuerpo = (await res.text()).replace(/\s+/g, ' ').slice(0, 300);
throw new Error(`Respuesta inesperada (${res.status}, ${tipo}). Inicio: ${cuerpo}`);
}
const datos = await res.json();
Basicamente pedimos una direccion y vemos que nos devuelve si es JSON son datos si es HTML es una pagina.
Se comprueba que la respeuesta sea la correcta es decir un JSON y si no lo es que se quede quieto me lance un error y muestre las primeros caracteres en este caso los 300 primeros que ha recibido, si es JSON pues todo esta ok.
Causas habituales cuando WordPress devuelve HTML
Si te pasa lo mismo, estas son las razones más comunes:
- Una protección anti-bots del hosting o de una capa intermedia, como en mi caso.
- Una redirección a otra dirección, a la página de acceso o a la versión segura.
- Un modo de mantenimiento activo en el CMS.
- Un error de PHP que se muestra como página en lugar de datos (menuda semanita lleva php).
- Un plugin de seguridad que bloquea a los clientes que no reconoce.
Para distinguirlas, mira el tipo de contenido y el principio de la respuesta, como hice yo.
Qué hice para que no tumbe la publicación
Lo primero no hacer todo a la vez, sino paso a paso:
- Comprobar el tipo de respuesta no fiarme del código 200.
- Reintentar con esperas cada vez más largas, pro si fue un fallo intermitente.
- Validar también las imágenes. Antes de guardar una imagen descargada, compruebo que de verdad lo es.
- Fallar a tiempo. Prefiero que el despliegue falle y se conserve la versión anterior de la web antes que publicar algo a medias y que se empeice a torcer todo.
- Hablar con el hosting para que trate esa consulta de otra manera. (esta vez no lo necesite).
¿Por qué WordPress devuelve HTML con código 200?
Porque la pantalla de espera es una página válida para el servidor, así que responde «correcto». Lo que cambia es el contenido, que no son datos.
¿Cómo sé si me está pasando a mí?
Imprime el tipo de contenido y los primeros 300 caracteres de la respuesta cuando no sea JSON. Si ves etiquetas de una página web, ya sabes que WordPress devuelve HTML
¿Basta con reintentar?
Alivia el problema, pero no lo elimina.
¿Debo desactivar la protección del hosting?
Respuesta corta NO, lo mejor hablar con tu proveedor para realizar ajsutes y el resto dejarlo tal y como esta.
Resumen:
Un código 200 no garantiza que lo que llega sean datos: comprueba siempre el tipo de contenido.
Si WordPress devuelve HTML en tu build, sospecha de una capa de protección y no de tu código.
Enseña en el error el principio de lo recibido: es la mejor pista que puedes tener.
Si quieres entender mejor cómo encaja esto en una web como esta, lee qué es un sitio headless y qué mejora.