codecamp

H3 示例总览与 Cookie 处理

前面六章把 H3 的概念、路由、核心 API、工具函数都铺开了。这一章换一种学法:不逐个列 API,而是把官方给出的六个可运行示例拆开讲透。每个示例都对应一类真实需求,照着改就能用。

六个示例覆盖什么

示例 解决的典型问题 对应小节
Cookies 在客户端存一小段数据 7.1
HTTP QUERY 用 GET 的语义但携带结构化请求体 7.2
Session 跨请求记住用户状态 7.3 / 7.4
Static Assets 把本地目录当静态资源对外提供 7.5
Streaming 分块、边生成边发送响应 7.6
Validation 用标准 schema 校验入参 7.7

这一节先讲最基础的 Cookie——几乎每个示例都会顺手用到它。

三个 Cookie 工具

H3 没有直接让你操作 req / res 上的 cookie,而是提供三个工具函数,全部以 event 为第一个参数:

  • setCookie(event, name, value, opts?):往响应里挂一个 Set-Cookie。
  • getCookie(event, name):从请求里读 cookie,没有时返回 undefined。
  • deleteCookie(event, name):让浏览器立刻删掉这个 cookie。

它们的本质是把「序列化 / 解析 cookie 头」这件事封装掉。你不必自己拼 name=value; Path=/; Max-Age=... 这种字符串,setCookie 会替你生成规范的 Set-Cookie 头。

设置 Cookie:选项怎么选

import { setCookie } from "h3";

// 在任意中间件或 handler 里调用即可,无需手动构造响应头
app.use(async (event) => {
  setCookie(event, "theme", "dark", {
    maxAge: 60 * 60 * 24 * 7, // 有效期 7 天,单位秒
    path: "/",                // 作用在整站
    httpOnly: true,           // 禁止前端 JS 读取,防 XSS 偷取
    sameSite: "lax",          // 默认即可,兼顾可用性与 CSRF 防护
    secure: true,             // 仅通过 HTTPS 传输
  });
  return "已写入主题偏好";
});

setCookie 的第三个参数能设的字段和浏览器原生 Set-Cookie 一致,常用的有:

  • maxAge / expires:过期时间,二选一;maxAge 是相对秒数,更直观。
  • path / domain:作用范围。
  • secure:只在 HTTPS 下发送。
  • httpOnly:前端脚本读不到。
  • sameSite:strict / lax / none。

⚠️ 两个最容易被用错的安全选项
- httpOnly:凡是存了登录态、会话 id 这类敏感值的 cookie,必须开 httpOnly。开着它,哪怕页面被注入了恶意脚本,也读不到这个 cookie,XSS 偷令牌的链条就此断掉。只有「前端 JS 确实需要读」的非敏感值(比如主题色)才考虑关掉。
- sameSite:现代浏览器默认就是 lax,它能挡掉大部分跨站 POST 带 cookie 的 CSRF 场景,同时又放行同站导航带来的 GET。除非你要做真正的跨站携带(如第三方嵌入),否则不要随手设成 none——none 还要求配合 secure: true。

读取与删除

读取就是一行,拿不到返回 undefined,所以判断是否存在要用 if (value !== undefined) 而不是假值判断(空字符串也是合法 cookie 值):

import { getCookie } from "h3";

app.use(async (event) => {
  const theme = getCookie(event, "theme"); // 没有就返回 undefined
  if (theme === undefined) {
    return "尚未设置主题";
  }
  return `当前主题:${theme}`;
});

删除是 setCookie 的语法糖——把值置空、把 maxAge 设 0,浏览器看到过期时间已到就会立刻清除:

import { deleteCookie } from "h3";

app.use(async (event) => {
  deleteCookie(event, "theme"); // 等价于 setCookie(event, "theme", "", { maxAge: 0 })
  return "主题已清除";
});

💡 删除时 path / domain 必须和当初设置时一致,否则浏览器会把它当成「另一个 cookie」而不去删目标。设置时用了 path: "/",删除也带上同样的 path 最稳妥。

用 curl 验证三条命令

Cookie 是「请求 ↔ 响应」之间来回带的东西,用 curl 验证最直观:

## 1) 设置:看响应头里的 Set-Cookie
curl -i -X POST http://localhost:3000/set

## 2) 读取:把上一步拿到的 cookie 回传,模拟浏览器再次访问
curl --cookie "theme=dark" http://localhost:3000/read

## 3) 删除:再看一次 Set-Cookie,应该是过期时间为 0 的空值
curl -i -X POST http://localhost:3000/del

第一条和第三条用 -i 是为了把响应头打印出来,直接看到 Set-Cookie: theme=dark; ... 和删除时的 Max-Age=0。第二条用 --cookie 手动带上 cookie,模拟浏览器自动回传的行为——这正是浏览器帮你做的事,你在代码里无需操心。

H3 社区生态
H3 HTTP QUERY 方法实战
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }