Nitro 的规则很简单:server/api/** → /api/**,server/routes/** → 原样路径,
文件名里 .get / .post / .patch 就是允许的 HTTP 方法,[id] 就是路由参数。
下面所有响应都是本地假数据,调用用 setTimeout 模拟,不发真的请求。
| 工具 | 拿什么 | 注意 |
|---|---|---|
getQuery(event) | 查询串 ?page=2&size=5 → 普通对象 | 全是字符串,要自己 Number() / 校验 |
getRouterParam(event, 'id') | /api/posts/7 里的 '7' | 同样是字符串;漏写会把 '7' 当数字比导致找不到 |
await readBody(event) | JSON / 表单请求体 | 没 Content-Type 或空 body 时返回 undefined,用 body ?? {} 兜 |
await readRawBody(event) | 原始字节/字符串(上传、webhook 验签) | 验签必须在解析 JSON 之前用 raw |
setHeader(event, k, v) | 响应头(缓存、CORS、request-id) | 必须在返回体之前调用 |
sendRedirect(event, url, 302) | 跳转 | 调用后要 return,否则 handler 继续往下跑 |
createError({ statusCode, statusMessage, data }) + throw | 错误响应 | 前端 useFetch 的 error.value 就来自这里;data 会带出去 |
event.context | 同一次请求内共享的袋子 | 中间件写的值,后面 handler 能读到 |
两个必踩的坑:① handler 的返回值就是响应体 —— return {a:1} 自动 JSON;return '文本' 是 text/plain;
想自己写 res 就 return 一个 undefined 并别再返回值。
② async handler 返回之后不能再写 res —— 响应已经发出去了,再 setHeader / res.write 会报
Cannot set headers after they are sent;需要「响应后再做的事」(发信、埋点)请放进 event.waitUntil() 或队列。