Saltar al contenido

Sesiones

Añadido en: astro@5.7.0

Las sesiones se usan para compartir datos entre peticiones para páginas renderizadas bajo demanda.

A diferencia de las cookies, las sesiones se almacenan en el servidor, por lo que puedes almacenar mayores cantidades de datos sin preocuparte por límites de tamaño o problemas de seguridad. Son útiles para almacenar cosas como datos de usuario, carritos de compra, y estado de formularios, y funcionan sin ningún JavaScript del lado del cliente:

src/components/CartButton.astro
---
export const prerender = false; // Not needed with 'server' output
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

Las sesiones requieren un storage driver para almacenar los datos de sesión. Los adaptadores de Node, Cloudflare, y Netlify configuran automáticamente un driver por defecto, pero otros adaptadores actualmente requieren que especifiques un driver manualmente.

astro.config.mjs
import { defineConfig, sessionDrivers } from 'astro/config'
import vercel from '@astrojs/vercel'
export default defineConfig({
adapter: vercel()
session: {
driver: sessionDrivers.lruCache({
max: 800,
}),
}
})

Consulta la opción de configuración session para más detalles sobre cómo establecer un storage driver, y otras opciones configurables.

Sobrescribir la configuración en tiempo de ejecución

Sección titulada “Sobrescribir la configuración en tiempo de ejecución”

Por defecto, los drivers de sesión se configuran en el momento del build, y cualquier variable de entorno usada se incrustará en el build. Esto significa que no puedes sobrescribir la configuración en tiempo de ejecución.

Cuando necesites una configuración diferente (p. ej. para conectarte a un servicio externo), defínela en un archivo separado. Luego usa ese archivo como el entrypoint del driver.

El siguiente ejemplo aprovecha la compatibilidad con Unstorage para configurar el driver de Redis en su propio entrypoint:

  1. Instala el paquete unstorage:

    Ventana de la terminal
    npm install unstorage
  2. Crea un archivo para la configuración del driver (p. ej. src/session-driver.ts) y exporta una función por defecto que devuelva la instancia del driver:

    src/session-driver.ts
    import type { SessionDriver } from "astro";
    import redisDriver from "unstorage/drivers/redis";
    import { REDIS_HOST, REDIS_PORT } from "astro:env";
    export default function (): SessionDriver {
    return redisDriver({
    host: REDIS_HOST,
    port: REDIS_PORT,
    });
    }
  3. Usa este archivo como el entrypoint del driver en tu configuración de Astro:

    astro.config.mjs
    import { defineConfig, envField, sessionDrivers } from "astro/config";
    import vercel from "@astrojs/vercel";
    export default defineConfig({
    adapter: vercel(),
    env: {
    REDIS_HOST: envField.string({ context: "server", access: "public", default: "localhost" }),
    REDIS_PORT: envField.number({ context: "server", access: "public", default: 6379 }),
    },
    session: {
    driver: {
    entrypoint: new URL('./src/session-driver.ts', import.meta.url),
    }
    }
    });

El objeto session te permite interactuar con el estado del usuario almacenado (p. ej. añadir items a un carrito de compra) y el ID de sesión (p. ej. eliminar la cookie del ID de sesión al cerrar sesión). El objeto es accesible como Astro.session en tus componentes y páginas de Astro y como objeto context.session en endpoints de API, middleware, y actions.

La sesión se genera automáticamente cuando se usa por primera vez y puede regenerarse en cualquier momento con session.regenerate() o destruirse con session.destroy().

Para muchos casos de uso, solo necesitarás usar session.get() y session.set().

Consulta la referencia de la API de Sessions para más detalles.

En componentes y páginas .astro, puedes acceder al objeto de sesión vía el objeto global Astro. Por ejemplo, para mostrar el número de items en un carrito de compra:

src/components/CartButton.astro
---
export const prerender = false; // Not needed with 'server' output
const cart = await Astro.session?.get('cart');
---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>

En los endpoints de API, el objeto de sesión está disponible en el objeto context. Por ejemplo, para añadir un item a un carrito de compra:

src/pages/api/addToCart.ts
import type { APIContext } from "astro";
export async function POST(context: APIContext) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json();
if(!data?.item) {
return new Response('Item is required', { status: 400 });
}
cart.push(data.item);
await context.session?.set('cart', cart);
return Response.json(cart);
}

En las actions, el objeto de sesión está disponible en el objeto context. Por ejemplo, para añadir un item a un carrito de compra:

src/actions/addToCart.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro/zod';
export const server = {
addToCart: defineAction({
input: z.object({ productId: z.string() }),
handler: async (input, context) => {
const cart = await context.session?.get('cart');
cart.push(input.productId);
await context.session?.set('cart', cart);
return cart;
},
}),
};

En el middleware, el objeto de sesión está disponible en el objeto context. Por ejemplo, para establecer la hora de la última visita en la sesión:

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
context.session?.set('lastVisit', new Date());
return next();
});

Por defecto, los datos de sesión no tienen tipo, y puedes almacenar datos arbitrarios en cualquier clave. Los valores se serializan y deserializan usando devalue, que es la misma librería usada en content collections y actions. Esto significa que los tipos soportados son los mismos, e incluyen strings, números, Date, Map, Set, URL, arrays, y objetos planos.

Opcionalmente puedes definir tipos de TypeScript para tus datos de sesión creando un archivo src/env.d.ts y añadiendo una declaración para el tipo App.SessionData:

src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}

Esto te permitirá acceder a los datos de sesión con type-checking y auto-completado en tu editor:

src/components/CartButton.astro
---
const cart = await Astro.session?.get('cart');
// const cart: string[] | undefined
const something = await Astro.session?.get('something');
// const something: any
Astro.session?.set('user', { id: 1, name: 'Houston' });
// Error: Argument of type '{ id: number; name: string }' is not assignable to parameter of type '{ id: string; name: string; }'.
---
Contribuir Comunidad Patrocinar