跳转到内容

Sessions

添加于: astro@5.7.0

会话(session)是用于存储 按需渲染页面 在请求间的数据。

不同于 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 端点、中间件和 action 中,则作为 context.session 对象被访问。

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

在大多数情况下,只需使用 Astro.session.get()Astro.session.set() 即可。

有关更多细节,请参阅 会话的 API 部分

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

src/components/CartButton.astro
---
export const prerender = false; // 无需使用 'server' 输出
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);
}

在 action 中,会话对象在 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();
});

默认情况下,会话数据的类型是未被定义的,你可以将任意数据存储在任何 key 中。使用 devalue 对值进行序列化和反序列化,该库与 content layer 和 action 所使用的库相同。这意味着支持的类型是相同的,包括字符串、数字、DateMapSetURL、数组和简单对象。

你可以通过创建 src/env.d.ts 文件并为 App.SessionData 添加类型,来选择性地为你的会话数据定义 TypeScript 类型:

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