其他
在 Bun 上用 Hono 构建 API:路由、请求响应…
适用于在 Bun 运行时使用 Hono 框架开发 API、REST 服务或 Web 应用时,快速实现路由、请求响应、中间件、校验、错误处理和类型安全客户端。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 40/100 ×0.15
适用场景
在 Bun 上用 Hono 构建 API特定
解决思路
- 创建 Hono 项目:`bun create hono my-app`。
- 进入项目目录:`cd my-app`。
- 安装依赖:`bun install`。
- 启动开发服务器:`bun run dev`。
- 从 `hono` 导入 Hono:`import { Hono } from 'hono';`。
- 创建应用实例:`const app = new Hono();`。
- 定义根路由返回文本:`app.get('/', (c) => c.text('Hello Hono!'));`。
- 定义 `/json` 路由返回 JSON:`app.get('/json', (c) => c.json({ message: 'Hello' }));`。
- 导出应用:`export default app;`。
- 注册 GET 路由:`app.get('/users', (c) => c.json([]));`。
- 注册 POST 路由:`app.post('/users', (c) => c.json({ created: true }));`。
- 注册 PUT 路由:`app.put('/users/:id', (c) => c.json({ updated: true }));`。
- 注册 DELETE 路由:`app.delete('/users/:id', (c) => c.json({ deleted: true }));`。
- 用 `app.all('/any', (c) => c.text('Any method'));` 处理所有 HTTP 方法。
- 用路径参数读取单个参数:`app.get('/users/:id', (c) => { const id = c.req.param('id'); return c.json({ id }); });`。
- 用 `c.req.param()` 解构读取多个路径参数:`app.get('/posts/:postId/comments/:commentId', (c) => { const { postId, commentId } = c.req.param(); return c.json({ postId, commentId }); });`。
- 用通配符路由并通过 `c.req.path` 获取路径:`app.get('/files/*', ...)`。
- 用类正则参数模式:`app.get('/user/:id{[0-9]+}', (c) => c.json({ id: c.req.param('id') }));`。
- 创建路由组:`const api = new Hono();`。
- 在路由组中注册 `api.get('/users', (c) => c.json([]));`。
- 在路由组中注册 `api.get('/posts', (c) => c.json([]));`。
- 挂载路由组:`app.route('/api/v1', api);`。
- 用 basePath 创建带基础路径的应用:`const app2 = new Hono().basePath('/api/v2');`。
- 在 basePath 应用上注册 `app2.get('/users', (c) => c.json([]));`,访问路径为 `/api/v2/users`。
- 在 POST `/submit` 中读取请求 URL:`console.log(c.req.url);`。
- 读取请求方法:`console.log(c.req.method);`。
- 读取请求头:`const auth = c.req.header('Authorization');`。
- 读取单个查询参数:`const page = c.req.query('page');`。
- 解构读取多个查询参数:`const { limit, offset } = c.req.query();`。
- 解析 JSON 请求体:`const json = await c.req.json();`。
- 解析文本请求体:`const text = await c.req.text();`。
- 解析表单请求体:`const form = await c.req.formData();`。
- 解析 ArrayBuffer 请求体:`const arrayBuffer = await c.req.arrayBuffer();`。
- 使用验证器后读取已解析请求体:`const body = c.req.valid('json');`。
- 返回 `c.json({ received: true });`。
- 返回文本响应:`c.text('Hello')`。
- 返回 JSON 响应:`c.json({ data: 'value' })`。
- 返回 HTML 响应:`c.html('<h1>Hello</h1>')`。
- 返回重定向:`c.redirect('/other', 302)`。
- 返回 Not Found:`c.notFound()`。
- 返回自定义响应:`c.body('Raw body', 200, { 'Content-Type': 'text/plain' })`。
- 返回带状态码的 JSON:`c.json({ error: 'Not found' }, 404)`。
- 设置响应头:`c.header('X-Custom', 'value');`,然后 `return c.json({ ok: true });`。
- 注册全局中间件:`app.use('*', async (c, next) => { ... });`。
- 在全局中间件中记录请求方法和 URL:`console.log(`${c.req.method} ${c.req.url}`);`。
- 在全局中间件中调用 `await next();` 继续执行。
- 注册路径特定中间件:`app.use('/api/*', async (c, next) => { ... });`。
- 在路径特定中间件中读取 `Authorization` 头:`const auth = c.req.header('Authorization');`。
- 如果 `Authorization` 缺失,返回 `c.json({ error: 'Unauthorized' }, 401)`。
- 如果 `Authorization` 存在,调用 `await next();`。
- 注册多个中间件:`app.use('/admin/*', authMiddleware, adminMiddleware);`。
- 定义受保护路由:`app.get('/api/data', (c) => c.json({ data: 'protected' }));`。
- 从 `hono/cors` 导入 `cors`。
- 从 `hono/logger` 导入 `logger`。
- 从 `hono/basic-auth` 导入 `basicAuth`。
- 从 `hono/bearer-auth` 导入 `bearerAuth`。
- 从 `hono/compress` 导入 `compress`。
- 从 `hono/etag` 导入 `etag`。
- 从 `hono/secure-headers` 导入 `secureHeaders`。
- 全局启用 CORS:`app.use('*', cors());`。
- 为 `/api/*` 配置 CORS:`app.use('/api/*', cors({ origin: 'https://example.com', allowMethods: ['GET', 'POST'] }));`。
- 全局启用 logger:`app.use('*', logger());`。
- 为 `/admin/*` 启用 Basic Auth:`app.use('/admin/*', basicAuth({ username: 'admin', password: 'secret' }));`。
- 为 `/api/*` 启用 Bearer Token:`app.use('/api/*', bearerAuth({ token: 'my-token' }));`。
- 全局启用压缩:`app.use('*', compress());`。
- 全局启用 ETag:`app.use('*', etag());`。
- 全局启用安全响应头:`app.use('*', secureHeaders());`。
- 从 `@hono/zod-validator` 导入 `zValidator`。
- 从 `zod` 导入 `z`。
- 定义用户校验 schema:`z.object({ name: z.string().min(1), email: z.email(), age: z.number().min(0).optional() });`。
- 在 `POST /users` 上使用 `zValidator('json', userSchema)` 校验 JSON body。
- 在校验后的处理器中通过 `c.req.valid('json')` 获取类型化数据并返回 `c.json({ created: user });`。
- 定义查询参数校验 schema:`z.object({ page: z.string().regex(/^\d+$/).optional(), limit: z.string().regex(/^\d+$/).optional() });`。
- 在 `GET /items` 上使用 `zValidator('query', querySchema)` 校验查询参数。
- 在校验后的处理器中通过 `c.req.valid('query')` 获取 `page` 和 `limit` 并返回 JSON。
- 定义上下文变量类型:`type Variables = { userId: string; isAdmin: boolean };`。
- 创建带 Variables 泛型的 Hono 实例:`const app = new Hono<{ Variables: Variables }>();`。
- 在中间件中用 `c.set('userId', '123')` 设置上下文变量。
- 在中间件中用 `c.set('isAdmin', true)` 设置上下文变量。
- 在处理器中用 `c.get('userId')` 读取上下文变量。
- 在处理器中用 `c.get('isAdmin')` 读取上下文变量,并返回 JSON。
- 从 `hono/http-exception` 导入 `HTTPException`。
- 抛出 HTTP 错误:`throw new HTTPException(401, { message: 'Unauthorized' });`。
- 注册全局错误处理器:`app.onError((err, c) => { ... });`。
- 在 `onError` 中判断 `err instanceof HTTPException` 并返回 `err.getResponse()`。
- 在 `onError` 中记录错误并返回 500 JSON:`c.json({ error: 'Internal Server Error' }, 500)`。
- 注册 notFound 处理器:`app.notFound((c) => c.json({ error: 'Not Found' }, 404));`。
- RPC 模式服务端:从 `hono` 导入 `Hono`,从 `hono/client` 导入 `hc`。
- 定义链式路由:`new Hono().get('/users', (c) => c.json([{ id: 1, name: 'Alice' }])).post('/users', async (c) => { const body = await c.req.json(); return c.json({ created: body }); });`。
- 导出类型:`export type AppType = typeof app;`。
- 客户端从 `hono/client` 导入 `hc`。
- 客户端从 `./server` 导入类型 `AppType`。
- 创建类型安全客户端:`const client = hc<AppType>('http://localhost:3000');`。
- 调用 `client.users.$get()` 发起类型安全 GET 请求。
- 用 `await res.json()` 获取类型化用户数据。
- 调用 `client.users.$post({ json: { name: 'Bob' } })` 发起类型安全 POST 请求。
- 排查 `Route not found`:错误原因是路径错误,修复是检查路由注册。
- 排查 `Body already read`:错误原因是重复解析,修复是只读取一次 body。
- 排查 `Validator error`:错误原因是输入无效,修复是检查 schema 定义。
- 排查 `Middleware order`:错误原因是执行顺序错误,修复是先注册中间件。
- 需要完整中间件参考或自定义中间件模式时,加载 `references/middleware-list.md`。
- 需要 OpenAPI/Swagger 集成或 API 文档生成时,加载 `references/openapi.md`。
适用边界 · 注意事项
- 不使用 Bun 或 Hono,而使用 Node.js/Express、Deno/Fresh 等其他运行时或框架时不适用。
- 不需要类型安全 RPC 或 Zod 校验时,不必强行引入相关依赖与模式。
- 无法使用或不想引入 Bun 作为运行时/包管理器时不适用。