Redirecciones: redirects y Astro.redirect
Dos maneras de mudar una URL sin romper los enlaces que apuntan a ella: la clave redirects de la configuración, declarativa y resuelta antes del despliegue, y Astro.redirect en el servidor, imperativa y atada a la petición. Y el código de estado como portador de intención: 301 permanente, 302 temporal, 307 que además preserva el método HTTP.
redirects: el mapa declarativo en la configuración
Cuando la mudanza es masiva, estable y no depende de nada que ocurra en la petición, no hay razón para escribir código: se declara. La clave redirects de astro.config es un objeto que mapea rutas de origen a rutas de destino, y Astro lo evalúa antes de intentar casar cualquier página de src/pages. Una entrada aquí tiene, por tanto, prioridad sobre un fichero del mismo nombre.
// astro.config.mjsimport { defineConfig } from 'astro/config';export default defineConfig({ redirects: { '/blog-viejo': '/blog', '/tienda/[id]': '/productos/[id]', '/panel': { status: 302, destination: '/login' }, },});Tres formas conviven en ese objeto y conviene distinguirlas. La cadena simple redirige una URL a otra con un 301 —permanente— por defecto. Los segmentos dinámicos entre corchetes reenvían familias enteras conservando el parámetro: /tienda/42 termina en /productos/42, y el [id] viaja de un lado al otro sin que escribas la correspondencia caso por caso. Y la forma de objeto, con status y destination, te deja fijar el código —un 302 para un desvío que quizá revoques mañana—.
Cómo se materializa depende del modo de renderizado, y es un matiz que muerde. En un sitio estático no hay servidor que emita un 301 de verdad en el momento: Astro genera para cada redirección una pequeña página HTML con una metaetiqueta de refresco, o —si tu adaptador lo soporta— un fichero de configuración que el host traduce a redirecciones nativas, más rápidas y correctas. En renderizado bajo demanda, en cambio, cada entrada de redirects se convierte en una respuesta HTTP real, con su código y su cabecera Location.
Astro.redirect: la decisión en tiempo de petición
El mapa declarativo cubre las mudanzas fijas, pero muchas redirecciones dependen de datos que solo existen en la petición: si hay sesión, qué rol tiene el usuario, si un recurso sigue publicado. Para eso, dentro de una página o un endpoint bajo demanda tienes Astro.redirect, que construye una respuesta de redirección que debes retornar.
---// src/pages/panel.astroexport const prerender = false;const sesion = Astro.cookies.get('sesion');if (!sesion) { return Astro.redirect('/login', 302);}---<h1>Panel privado</h1>El detalle que más veces cuesta un disgusto es el return. Astro.redirect no interrumpe la ejecución por sí solo: fabrica una respuesta con la cabecera Location apuntando al destino, pero solo surte efecto si la devuelves. Olvidar el return deja que el frontmatter siga corriendo y que la plantilla se pinte igual —el panel privado se renderiza sin sesión, exactamente lo que creías haber impedido—. Piensa en Astro.redirect como en extender un billete de salida: tenerlo en la mano no te saca de la sala; hay que entregarlo.
El segundo argumento es el código de estado, y su ausencia también tiene consecuencias: si no lo indicas, Astro.redirect usa 302 por defecto. Ese valor es sensato para un desvío condicional como el del ejemplo, pero es el equivocado para una mudanza permanente, y elegir a ciegas es dejar que un detalle importante lo decida la inercia.
Astro.redirect no es exclusivo de las páginas: en un endpoint —un fichero que exporta funciones por método HTTP— sirve igual para redirigir desde una API, por ejemplo tras procesar un envío y querer llevar al visitante a una página de confirmación.
// src/pages/api/enviar.tsexport const prerender = false;export async function POST({ request, redirect }) { const datos = await request.formData(); await guardar(datos); return redirect('/gracias');}En un endpoint recibes redirect dentro del contexto, y el patrón es idéntico al de una página: construyes la respuesta y la retornas. Lo único que cambia es dónde vive el código; la mecánica del desvío, y la obligación de retornarlo, son las mismas.
Un peligro emparentado es la cadena de redirecciones. Si una regla manda /a a /b y otra manda /b a /c, el cliente hace varios viajes para llegar a destino, y cada salto cuesta latencia; peor aún, un ciclo —/a a /b y /b a /a— deja al navegador dando vueltas hasta que aborta con un error. Al declarar redirects masivos tras una reestructuración, conviene apuntar siempre al destino final directo, no encadenar mudanzas sobre mudanzas que se fueron acumulando con el tiempo.
El código de estado: 301, 302 y 307
Aquí es donde el enrutado avanzado se separa del ingenuo. El número que acompaña a una redirección no es adorno: le dice al cliente qué clase de mudanza es esta, y esa información cambia el comportamiento de cachés, buscadores y del propio navegador. Hay dos ejes independientes que conviene no confundir: permanencia y preservación del método.
En el eje de la permanencia, un 301 dice esto se ha mudado para siempre: los buscadores transfieren la autoridad de la vieja URL a la nueva y la memorizan, y los navegadores cachean el desvío de forma agresiva —a veces tanto que revertirlo cuesta—. Un 302 dice es temporal, no actualices tus enlaces: el recurso vive normalmente en el origen y ahora mismo lo desviamos, pero mañana quizá no.
El segundo eje es más sutil y suele ignorarse. Cuando la petición original es un POST con un cuerpo —el envío de un formulario—, ¿qué método usa el cliente al seguir la redirección? Históricamente, muchos navegadores convierten un 301 o un 302 en un GET, descartando el cuerpo. Para cuando eso no puede pasar existe el 307: un desvío temporal que obliga a repetir el método y el cuerpo intactos, de modo que un POST sigue siendo un POST. Su pareja permanente es el 308. Si alguna vez rediriges el destino de un formulario, 301 y 302 son trampas; 307 y 308 son la respuesta correcta.
---// redirigir un POST sin degradarlo a GETexport const prerender = false;if (Astro.request.method === 'POST') { return Astro.redirect('/procesar', 307);}---Elegir bien es, en el fondo, decir la verdad sobre lo que ha pasado. Una reestructuración definitiva pide 301; un mantenimiento o un flujo de acceso pasajero pide 302; el reenvío de una operación con cuerpo pide 307. El código equivocado no rompe la página, pero desinforma a quien te lee: un 302 en una mudanza real impide que los buscadores consoliden tu autoridad en la URL nueva, y un 301 en un desvío temporal deja a los clientes memorizando algo que dejará de ser cierto.
En la práctica, la elección entre los dos mecanismos y el código correcto se reduce a unas pocas preguntas:
- ¿La mudanza es fija y no depende de la petición? Declárala en
redirects. - ¿Depende de datos como la sesión, el rol o el estado del recurso? Emítela con
Astro.redirect. - ¿El cambio es definitivo? Usa
301. ¿Es provisional? Usa302. - ¿Rediriges una operación con cuerpo, un
POST? Preserva el método con307o308.