Skip to content

会话

Added in: astro@5.7.0

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

¥Sessions are used to share data between requests for on-demand rendered pages.

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

¥Unlike cookies, sessions are stored on the server, so you can store larger amounts of data without worrying about size limits or security issues. They are useful for storing things like user data, shopping carts, and form state, and they work without any client-side 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>

¥Configuring sessions

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

¥Sessions require a storage driver to store the session data. The Node, Cloudflare, and Netlify adapters automatically configure a default driver for you, but other adapters currently require you to specify a driver manually.

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

See the session configuration option for more details on setting a storage driver, and other configurable options.

¥Interacting with session data

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

¥The session object allows you to interact with the stored user state (e.g. adding items to a shopping cart) and the session ID (e.g. deleting the session ID cookie when logging out). The object is accessible as Astro.session in your Astro components and pages and as context.session object in API endpoints, middleware, and actions.

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

¥The session is generated automatically when it is first used and can be regenerated at any time with session.regenerate() or destroyed with session.destroy().

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

¥For many use cases, you will only need to use session.get() and session.set().

See the Sessions API reference for more details.

¥Astro components and pages

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

¥In .astro components and pages, you can access the session object via the global Astro object. For example, to display the number of items in a shopping cart:

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 endpoints

在 API 端点中,会话对象在 context 对象上可用。例如,要将商品添加到购物车:

¥In API endpoints, the session object is available on the context object. For example, to add an item to a shopping cart:

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);
}

¥Actions

在操作中,会话对象在 context 对象上可用。例如,要将商品添加到购物车:

¥In actions, the session object is available on the context object. For example, to add an item to a shopping cart:

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;
},
}),
};

¥Middleware

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

¥In middleware, the session object is available on the context object. For example, to set the last visit time in the session:

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

¥Session data types

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

¥By default session data is untyped, and you can store arbitrary data in any key. Values are serialized and deserialized using devalue, which is the same library used in content collections and actions. This means that supported types are the same, and include strings, numbers, Date, Map, Set, URL, arrays, and plain objects.

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

¥You can optionally define TypeScript types for your session data by creating a src/env.d.ts file and adding a declaration for the App.SessionData type:

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

这将允许你在编辑器中使用类型检查和自动补齐访问会话数据:

¥This will allow you to access the session data with type-checking and auto-completion in your 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; }'.
---
Astro v5.7 中文网 - 粤ICP备13048890号