H3 Cookie 工具
2026-10-30 17:48 更新
Cookie 工具一共八个函数,核心是四个读写 + 三个分块处理 + 一个批量校验。它们底层用 cookie-es,所以在 v2 里 splitCookiesString 这类旧工具已经不在 h3 里了(改用 cookie-es 的 splitSetCookieString)。
四个基础操作
import { H3, getCookie, setCookie, deleteCookie, parseCookies } from "h3";
const app = new H3()
.post("/login", (event) => {
// 写:只往 event.res 追加 Set-Cookie,本身不产生响应
setCookie(event, "token", "abc123", {
httpOnly: true, // JS 读不到,防 XSS 窃取
secure: true, // 只在 HTTPS 下发送
sameSite: "lax", // 防 CSRF 的基础设置
path: "/",
maxAge: 60 * 60 * 24 * 7,
});
return { ok: true };
})
.get("/me", (event) => {
// 读单个:不存在返回 undefined
const token = getCookie(event, "token");
// 一次读全部,值是字符串;同名多值会是数组
const all = parseCookies(event);
return { token, count: Object.keys(all).length };
})
.post("/logout", (event) => {
// 删:实际是设一个立即过期的同名 cookie
deleteCookie(event, "token", { path: "/" });
return { ok: true };
});
三条实践规则:
path要一致。写入时用了path: "/admin",删除时也必须写同样的path,否则删不掉——浏览器按(name, domain, path)三元组匹配 cookie。- 多个
Set-Cookie不要用headers.get读。标准Headers会把它们合并成一个字符串,v2 提供event.res.headers.getSetCookie()返回数组(3.4 讲过这个 API)。 - 敏感内容不要明文放 cookie。cookie 在客户端可读、可篡改,需要签名或加密就走会话(6.6),或者直接用社区库
unjwt(6.10)。
超过 4KB 自动分块
浏览器对单个 cookie 有容量上限(约 4KB),存大一点的 JSON 就会静默丢失。H3 提供三个分块版本:
import { H3, setChunkedCookie, getChunkedCookie, deleteChunkedCookie } from "h3";
const app = new H3()
.post("/save", (event) => {
// 值短就写普通 cookie;超过分块阈值(默认 4000 字符)会自动拆成多个
setChunkedCookie(event, "prefs", JSON.stringify({ theme: "dark", langs: ["zh", "en"] }));
return { ok: true };
})
.get("/load", (event) => {
// 读取时自动把所有分片拼回原值,不需要你知道拆成了几块
const raw = getChunkedCookie(event, "prefs");
return { prefs: raw ? JSON.parse(raw) : null };
})
.post("/clear", (event) => {
// 删除会连同所有分片一起清掉
deleteChunkedCookie(event, "prefs");
return { ok: true };
});
实现细节值得知道,排查问题时有用:
| 细节 | 说明 |
|---|---|
| 阈值 | 默认每片 4000 字符,可用 chunkMaxLength 调整 |
| 主 cookie | 存一个以 __chunked__ 开头的计数标记,不存数据本身 |
| 分片 cookie | 按序号命名的独立 cookie,读取时按计数逐个取 |
| 只有一个分片时 | 退化为普通 cookie,不写标记 |
| 单个字符都放不下 | 直接抛错,而不是写出坏数据 |
所以分块 cookie 在浏览器 DevTools 里会显示成好几条,看起来像重复写入,其实是设计如此。
批量校验:getValidatedCookies
import { H3, getValidatedCookies } from "h3";
import { z } from "zod";
const app = new H3().get("/settings", async (event) => {
const cookies = await getValidatedCookies(
event,
z.object({ theme: z.enum(["light", "dark"]) }),
// 校验失败时自定义错误,默认抛 400
{ onError: ({ issues }) => ({ statusText: "cookie 不合法", message: String(issues) }) },
);
return cookies;
});
它和 readValidatedBody、getValidatedQuery 是同一套校验机制,只是作用对象换成了全部 cookie。
排查表
| 现象 | 最可能原因 | 处理 |
|---|---|---|
| 删不掉 cookie | 写入与删除的 path/domain 不一致 |
两处保持完全相同 |
| 大 JSON 存进 cookie 后读不到 | 超过 4KB 被浏览器丢弃 | 改用 setChunkedCookie |
| 线上 HTTPS 下 cookie 不发送 | 漏了 secure,或反向代理下协议判断错误 |
检查 secure 与代理解析 |
只读到最后一个 Set-Cookie |
用了 headers.get |
改 headers.getSetCookie() |
getChunkedCookie 返回 undefined |
分片缺失(用户清了部分 cookie) | 按整体失效处理,重新写入 |
| 服务端拿到的值带引号 | 值被编码,读取端没解码 | 统一用 getCookie 读,或显式 decode |
延伸阅读
- Cookie 与会话的配合方式:见 6.6 安全工具
Set-Cookie在 v2 里的读取方式:见 8.1 v1 到 v2 迁移:核心变更- 一个完整的中小型会话实现:见 7.3 会话基础
以上内容是否对您有帮助:
← H3 响应工具

TRAE-AI编程


更多建议: