Rewrites con Astro.rewrite()
Una operación emparentada con la redirección pero de naturaleza opuesta: la reescritura sirve el contenido de otra ruta sin mover la barra de direcciones. Una sola petición, la misma URL visible, contenido distinto por dentro. Cómo se invoca Astro.rewrite, qué acepta como destino, por qué solo existe bajo demanda y en qué se diferencia, punto por punto, de un redirect.
Una redirección le dice al navegador ve a otra parte: cambia la URL de la barra y provoca una segunda petición. Su primo cercano hace algo aparentemente parecido pero opuesto en el fondo: Astro.rewrite sirve el contenido de otra ruta sin que la URL cambie ni el navegador vuelva a pedir nada. El visitante pidió una dirección y, por dentro, el servidor decide renderizar el componente de otra, entregándolo bajo la URL original. La diferencia no es cosmética: separa el concepto de dónde estás del de qué se te muestra, y abre la puerta a servir contenido condicional, mudar rutas sin romper direcciones y pintar páginas de error con su maqueta completa, todo sin un solo viaje de ida y vuelta extra.
- Servir el contenido de otra ruta con
Astro.rewriteconservando la URL visible. - Distinguir una reescritura de una redirección en peticiones, URL y estado.
- Invocar
Astro.rewritecon una ruta, unaURLo unaRequest. - Entender por qué la reescritura solo existe en renderizado bajo demanda.
Astro.rewrite: servir otro contenido sin mover la URL
Astro.rewrite toma un destino y renderiza el contenido de esa ruta como respuesta a la petición actual, sin tocar la barra de direcciones. Es una operación interna del servidor: el visitante nunca se entera de que lo que ve vive, en el árbol de ficheros, en otro sitio.
---
// src/pages/[handle].astro
export const prerender = false;
const usuario = await buscarUsuario(Astro.params.handle);
if (!usuario) {
return Astro.rewrite('/404');
}
---
<h1>{usuario.nombre}</h1>
Ese Astro.rewrite('/404') hace que, cuando el handle no corresponde a nadie, el servidor renderice el contenido de tu src/pages/404.astro —con su layout, sus estilos, su buscador— pero lo entregue bajo la URL que el visitante pidió. No hay salto, no hay parpadeo, no hay una segunda petición: la dirección sigue siendo la del perfil inexistente y, sin embargo, lo que se pinta es tu página de error cuidada. Como con Astro.redirect, la llamada construye una respuesta que debes retornar; olvidarlo deja seguir el render y romper al leer datos de un usuario nulo.
La potencia del gesto está en que desacopla dos cosas que solemos confundir: la URL, que es la identidad pública de la petición, y el componente que la atiende, que es un detalle interno. Con una reescritura puedes cambiar el segundo sin tocar el primero, y esa libertad es la que da a la reescritura sus usos más interesantes, todos variaciones de una misma idea: mismo nombre público, distinta implementación por dentro.
Reescribir no es redirigir: una petición frente a dos
La confusión entre rewrite y redirect es tan común que merece desmontarse paso a paso, porque eligen mal quienes no ven la diferencia. Ambas mandan al visitante a otro contenido, pero el camino es distinto y las consecuencias también.
Una redirección es una conversación de dos turnos. El servidor responde a la primera petición con un código 30x y una cabecera Location; el navegador lee esa cabecera, actualiza su barra de direcciones y emite una segunda petición a la nueva URL; solo entonces recibe el contenido. El visitante ve cómo la dirección cambia, y hay dos viajes por la red.
Una reescritura es un solo turno. El servidor recibe la petición, decide por dentro renderizar otra ruta, y devuelve ese contenido en la misma respuesta. El navegador no sabe que hubo un cambio de ruta interno: pidió una URL, recibió contenido, y la barra de direcciones no se movió. Un viaje, una URL, contenido de otra parte.
flowchart TD
RQ[peticion a barra panel] --> DE{redirect o rewrite}
DE -->|redirect| RE[respuesta 30x con Location]
RE --> NB[el navegador pide barra login]
NB --> UB[la barra de direcciones cambia]
DE -->|rewrite| RW[el servidor renderiza el login por dentro]
RW --> SB[misma URL una sola peticion]
style RQ fill:#89b4fa,color:#11111b
style UB fill:#f9e2af,color:#11111b
style SB fill:#a6e3a1,color:#11111bElige por lo que quieres que le pase a la URL. Si quieres que el visitante acabe en otra dirección —y que la comparta, la guarde, la vea en su barra—, es una redirección. Si quieres que permanezca en la dirección que pidió pero reciba otro contenido por dentro, es una reescritura. Redirect mueve al visitante; rewrite mueve el contenido hacia el visitante. Una cambia la identidad de la página, la otra solo su relleno.
Hay también una diferencia de coste que a veces inclina la balanza. La redirección paga un viaje de red extra: la respuesta 30x viaja, el navegador la interpreta y vuelve a pedir. La reescritura resuelve todo en el servidor dentro de la misma petición, sin ese ida y vuelta. Para una página de error o una variante servida al vuelo, evitar el segundo viaje se nota, sobre todo en conexiones lentas.
Dónde vive, qué acepta y las formas de invocarla
Como toda operación que decide en el momento de la petición, Astro.rewrite solo tiene sentido en renderizado bajo demanda: necesita un servidor vivo que reciba la URL, tome la decisión y renderice otra ruta al vuelo. En un sitio puramente estático no hay tal momento —todo se horneó en el build—, así que la reescritura no es una herramienta disponible allí. Es, por naturaleza, un mecanismo de servidor.
El destino admite varias formas, y conviene conocerlas. La más habitual es una ruta como cadena —Astro.rewrite('/404')—. Pero también acepta una instancia de URL, útil cuando la compones a partir de datos, y una Request completa, para casos avanzados donde quieres controlar cabeceras o método de la petición reescrita. Sea cual sea la forma, Astro vuelve a entrar en su fase de enrutado con ese destino: localiza la ruta que casa, ejecuta de nuevo el middleware y renderiza el componente correspondiente.
---
export const prerender = false;
// segun una bandera, servir la variante sin cambiar la URL
const variante = Astro.cookies.get('experimento')?.value;
if (variante === 'b') {
return Astro.rewrite('/landing-b');
}
---
<h1>Landing A</h1>
Los usos naturales de la reescritura son todos variaciones de mismo nombre, distinta implementación:
- Servir una página de error con su maqueta completa bajo la URL que falló, sin desviar al visitante.
- Atender un idioma distinto reescribiendo hacia la variante localizada según la cabecera o una cookie.
- Mostrar una página de mantenimiento para una sección entera sin cambiar sus direcciones.
- Repartir tráfico entre variantes en un experimento A/B manteniendo una sola URL pública.
- Servir contenido heredado desde una ruta nueva sin romper los enlaces antiguos.
La reescritura también vive en el middleware, donde encaja de forma natural. La función next que recibe el middleware acepta, además de su uso normal, una ruta a la que reescribir: llamar a next('/otra-ruta') reencamina la petición hacia ese destino antes de renderizar. Colocada ahí, una reescritura se vuelve una política transversal —internacionalización, mantenimiento, banderas de funcionalidad— que se aplica a familias enteras de rutas sin tocar cada página.
// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware((context, next) => {
if (enMantenimiento && !context.url.pathname.startsWith('/admin')) {
return next('/mantenimiento');
}
return next();
});
Aquí next('/mantenimiento') reescribe toda petición que no sea del panel hacia la página de mantenimiento, sin cambiar la URL y desde un solo punto del código. Una llamada a next sin argumento sigue el flujo normal; con una ruta, reescribe. Esa capacidad de reencaminar desde el middleware es lo que convierte la reescritura en una política de sitio, y no en un parche repetido página por página.
El estado de la respuesta y el SEO
Una duda frecuente es qué código de estado sale cuando reescribes. La respuesta es limpia: la respuesta lleva el estado que produzca la ruta renderizada, no la pedida. Si reescribes hacia una página normal, sale un 200, porque esa página se renderiza con normalidad; si reescribes hacia tu ruta de error /404, Astro la trata como la página de error que es y emite el estado que corresponde. Por eso reescribir a /404 es el patrón idóneo para un recurso ausente: el visitante conserva su URL, ve tu maqueta de error completa y el cliente recibe el 404 honesto que esperaba.
Ese desacople entre URL pedida y contenido servido tiene una cara delicada en el SEO, y conviene mirarla de frente. Mientras la reescritura sea hacia dentro —servir un error, atender un idioma, mostrar una variante— no hay problema: la URL pública sigue siendo única y significativa. El riesgo aparece si usas reescrituras para que varias URLs distintas muestren, en silencio, exactamente el mismo contenido: los buscadores lo verán como duplicado y no sabrán cuál indexar. Si dos direcciones deben mostrar lo mismo, decláralo con una etiqueta canónica o resuélvelo con una redirección; no lo escondas tras un espejo opaco.
Un detalle que sorprende a quien llega de otros frameworks: reescribir no sirve un fragmento ya cocinado, sino que vuelve a entrar en la tubería de enrutado y renderiza el destino desde cero, con su propia ejecución de middleware sobre la petición reescrita. Es potente —tus políticas transversales siguen aplicándose al contenido reescrito—, pero exige cuidado para no montar reescrituras que se disparen unas a otras en cadena. Piensa cada rewrite como una vuelta completa por el enrutador, no como un simple intercambio de plantilla.
Que la URL no cambie es su virtud y su riesgo. Servir una página de error con rewrite es excelente: el visitante conserva la dirección rota, ve tu maqueta y el estado es el correcto. Pero reescribir contenido legítimo de forma opaca puede confundir: dos URLs distintas que muestran lo mismo sin declararlo diluyen el SEO y desconciertan a quien compara direcciones. La reescritura no exime de pensar en identidad: si dos rutas deben ser la misma cosa, quizá lo honesto sea una redirección o una etiqueta canónica, no un espejo silencioso.
Misma URL, otro contenido
El visitante ve la direccion que pidio; por dentro se renderiza otra ruta. Una sola peticion.
Redirect mueve, rewrite sirve
Redirect cambia la URL y provoca un segundo viaje. Rewrite conserva la URL en un solo viaje.
Solo bajo demanda
Necesita un servidor que decida en la peticion. En estatico no existe: todo estaba horneado.
Ruta, URL o Request
El destino puede ser una cadena, una URL compuesta o una Request completa para casos avanzados.
Para apreciar lo que Astro.rewrite realmente ofrece, conviene subir un peldaño y pensar qué es una URL. Solemos tratarla como si fuera un fichero: pedir una dirección es abrir un documento que está ahí, en ese sitio. Pero esa intuición, heredada de los servidores de ficheros de los años noventa, es una simplificación que el enrutado moderno hace tiempo que dejó atrás. Una URL no es una ubicación, es un nombre: una identidad estable y pública que designa un recurso, con total independencia de dónde y cómo se produzca ese recurso por dentro. La redirección y la reescritura son las dos operaciones que explotan esa independencia, cada una por un lado. La redirección dice este nombre ya no es el bueno, usa este otro, y lo hace en público, cambiando la identidad ante los ojos del visitante. La reescritura dice este nombre sigue siendo el bueno, pero lo atiendo con otra maquinaria, y lo hace en privado, preservando la identidad y variando solo la implementación que la respalda. Esta distinción —entre la interfaz que un nombre promete y la implementación que la cumple— es una de las ideas más fértiles de toda la informática: es la misma que separa una función de su cuerpo, una llamada de red de la máquina que la sirve, un puntero del objeto al que apunta. La indirección, decía el viejo aforismo, resuelve cualquier problema en informática, y una reescritura es indirección pura aplicada al enrutado: una capa que traduce el nombre que el mundo conoce a la ruta que hoy resulta que lo implementa. Su poder es que puedes reorganizar tus tripas —renombrar componentes, servir una variante de experimento, atender un idioma con otra plantilla, mostrar un error con su maqueta— sin romper una sola de las direcciones que el mundo ya memorizó. La URL, ese nombre público, queda blindada frente a tus decisiones internas. Entender rewrite no es aprender una función más: es interiorizar que las direcciones de tu sitio son un contrato de nombres que puedes honrar con la implementación que quieras, y que esa libertad, bien usada, es lo que te deja evolucionar sin traicionar a quien confió en tus URLs.
- En una ruta
[handle].astrobajo demanda, cuando el recurso no exista, devuelveAstro.rewrite('/404')y comprueba que la URL sigue siendo la pedida mientras se pinta tu página de error. - Compara ese comportamiento con
Astro.redirect('/404'): observa cómo el redirect cambia la barra de direcciones y provoca una segunda petición. - Reescribe según una cookie de experimento hacia
/landing-ao/landing-by verifica que ambas variantes se sirven bajo la misma URL. - Lleva esa misma reescritura al middleware con
next('/mantenimiento')y razona por qué ahí se convierte en una política que cubre muchas rutas a la vez.