跳转到内容

会话

添加于: astro@5.7.0

会话用于在按需渲染页面的请求之间共享数据。

cookies 不同,会话数据存储在服务器上,因此你可以存储更大量的数据而无需担心大小限制或安全问题。它们可用于存储用户数据、购物车和表单状态等内容,并且无需任何客户端 JavaScript 即可工作。

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>

会话需要一个存储驱动程序来存储会话数据。 NodeCloudflareNetlify 适配器会自动为你配置一个默认驱动程序,但其他适配器目前需要你手动指定驱动程序

astro.config.mjs
{
adapter: vercel(),
session: {
driver: "redis",
},
}

有关设置存储驱动程序和其他可配置选项的更多详细信息,请参阅session 配置选项

session 对象允许你与存储的用户状态(例如,向购物车添加商品)和会话 ID(例如,注销时删除会话 ID cookie)进行交互。该对象在 Astro 组件和页面中可以通过 Astro.session 访问,在 API 端点、中间件和操作中可以通过 context.session 对象访问。

会话在首次使用时会自动生成,并可以随时使用 session.regenerate() 重新生成,或使用 session.destroy() 销毁。

对于许多用例,你只需要使用 session.get()session.set()

更多详细信息请参阅会话 API 参考

.astro 组件和页面中,你可以通过全局 Astro 对象访问会话对象。例如,要显示购物车中的商品数量

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>

在 API 端点中,会话对象可在 context 对象上使用。例如,要向购物车添加一件商品

src/pages/api/addToCart.ts
export async function POST(context: APIContext) {
const cart = await context.session?.get('cart') || [];
const data = await context.request.json<{ item: string }>();
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);
}

在操作中,会话对象可在 context 对象上使用。例如,要向购物车添加一件商品

src/actions/addToCart.ts
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
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;
},
}),
};

在中间件中,会话对象可在 context 对象上使用。例如,在会话中设置上次访问时间

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

默认情况下,会话数据是无类型的,你可以在任何键中存储任意数据。值使用 devalue 进行序列化和反序列化,这与内容集合和操作中使用的库相同。这意味着支持的类型是相同的,包括字符串、数字、DateMapSetURL、数组和普通对象。

你可以选择性地为会话数据定义 TypeScript 类型,方法是创建一个 src/env.d.ts 文件并为 App.SessionData 类型添加一个声明

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

这将允许你在编辑器中访问会话数据时获得类型检查和自动补全功能

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; }'.
---
贡献 社区 赞助