# 路由基础

URL: https://caijiao.org/hono/02-core/01-routing
Source: docs/hono/02-core/01-routing.md
Description: 学习 Hono 的 GET、POST、动态参数、通配符、路由分组和模块化路由写法。

Hono 路由用于把 HTTP 方法和路径映射到处理函数。处理函数接收 `Context`，并返回一个响应。

## 基本路由

```ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.text('Home'))
app.get('/posts', (c) => c.json([{ id: 1, title: 'Hono 入门' }]))
app.post('/posts', async (c) => {
  const body = await c.req.json()
  return c.json({ id: 2, ...body }, 201)
})
```

常用方法包括：

| 方法 | 用途 |
| --- | --- |
| `app.get()` | 查询资源。 |
| `app.post()` | 创建资源或提交动作。 |
| `app.put()` | 整体更新资源。 |
| `app.patch()` | 局部更新资源。 |
| `app.delete()` | 删除资源。 |
| `app.all()` | 匹配所有 HTTP 方法。 |

## 动态参数

路径中使用 `:name` 定义动态参数：

```ts
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id })
})
```

多个参数也可以同时使用：

```ts
app.get('/teams/:teamId/users/:userId', (c) => {
  return c.json({
    teamId: c.req.param('teamId'),
    userId: c.req.param('userId'),
  })
})
```

## 查询参数

```ts
app.get('/search', (c) => {
  const keyword = c.req.query('q') ?? ''
  const page = Number(c.req.query('page') ?? '1')

  return c.json({ keyword, page })
})
```

如果同名查询参数出现多次，可以用 `queries()`：

```ts
app.get('/tags', (c) => {
  const tags = c.req.queries('tag') ?? []
  return c.json({ tags })
})
```

## 通配符路径

通配符适合静态资源、代理和兜底路由：

```ts
app.get('/assets/*', (c) => {
  return c.text(`asset path: ${c.req.path}`)
})
```

注意不要把通配符路由放在过早的位置，否则可能吞掉后续更具体的路由。

## 模块化路由

当路由变多时，把相关路由拆成子应用：

```ts
// routes/users.ts
import { Hono } from 'hono'

export const users = new Hono()

users.get('/', (c) => c.json([{ id: 1, name: 'Ada' }]))
users.get('/:id', (c) => c.json({ id: c.req.param('id') }))
```

在入口文件挂载：

```ts
import { Hono } from 'hono'
import { users } from './routes/users'

const app = new Hono()

app.route('/users', users)

export default app
```

这样 `/users` 命中列表，`/users/:id` 命中详情。

## 路由设计建议

- 用名词表示资源，例如 `/users`、`/posts`、`/orders`。
- 使用 HTTP 方法表达动作，不要滥用 `/createUser`、`/deleteUser`。
- 对公开 API 保持稳定路径，破坏性变更使用版本前缀，例如 `/v1/users`。
- 把鉴权、中间件和验证放在路由附近，避免全局逻辑难以追踪。
