会话
添加于: astro@5.7.0
会话用于在按需渲染页面的请求之间共享数据。
与 cookies
不同,会话数据存储在服务器上,因此你可以存储更大量的数据而无需担心大小限制或安全问题。它们可用于存储用户数据、购物车和表单状态等内容,并且无需任何客户端 JavaScript 即可工作。
---export const prerender = false; // Not needed with 'server' outputconst cart = await Astro.session?.get('cart');---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>
配置会话
标题为“配置会话”的部分会话需要一个存储驱动程序来存储会话数据。 Node、Cloudflare 和 Netlify 适配器会自动为你配置一个默认驱动程序,但其他适配器目前需要你手动指定驱动程序。
{ 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 组件和页面”的部分在 .astro
组件和页面中,你可以通过全局 Astro
对象访问会话对象。例如,要显示购物车中的商品数量
---export const prerender = false; // Not needed with 'server' outputconst cart = await Astro.session?.get('cart');---
<a href="/checkout">🛒 {cart?.length ?? 0} items</a>
API 端点
标题为“API 端点”的部分在 API 端点中,会话对象可在 context
对象上使用。例如,要向购物车添加一件商品
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
对象上使用。例如,要向购物车添加一件商品
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
对象上使用。例如,在会话中设置上次访问时间
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => { context.session?.set('lastVisit', new Date()); return next();});
会话数据类型
标题为“会话数据类型”的部分默认情况下,会话数据是无类型的,你可以在任何键中存储任意数据。值使用 devalue 进行序列化和反序列化,这与内容集合和操作中使用的库相同。这意味着支持的类型是相同的,包括字符串、数字、Date
、Map
、Set
、URL
、数组和普通对象。
你可以选择性地为会话数据定义 TypeScript 类型,方法是创建一个 src/env.d.ts
文件并为 App.SessionData
类型添加一个声明
declare namespace App { interface SessionData { user: { id: string; name: string; }; cart: string[]; }}
这将允许你在编辑器中访问会话数据时获得类型检查和自动补全功能
---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; }'.---
这仅用于类型检查,不影响会话的运行时行为。当用户已在会话中存储数据时,如果更改类型,请格外小心,因为这可能会导致运行时错误。