# CORS 与 Logger

URL: https://caijiao.org/hono/04-middleware/01-cors-logger
Source: docs/hono/04-middleware/01-cors-logger.md
Description: 学习 Hono 内置 CORS 与 Logger 中间件的用法、注册顺序、跨域配置和生产环境日志建议。

CORS 和日志是 API 项目最常见的中间件。Hono 内置了 `cors` 和 `logger`，可以直接使用。

## 启用 Logger

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

const app = new Hono()

app.use(logger())

app.get('/health', (c) => c.json({ ok: true }))
```

Logger 会输出请求方法、路径、响应状态码和耗时，适合开发环境快速观察请求。

生产环境中，建议使用结构化日志，把请求 ID、用户 ID、状态码、耗时和错误信息输出到日志平台。

## 启用 CORS

```ts
import { cors } from 'hono/cors'

app.use('/api/*', cors())
```

如果前端和 API 不在同一个域名下，就需要配置 CORS。

## 指定跨域来源

```ts
app.use(
  '/api/*',
  cors({
    origin: 'https://example.com',
    allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    allowHeaders: ['Content-Type', 'Authorization'],
    credentials: true,
  }),
)
```

多个来源：

```ts
const allowedOrigins = ['https://app.example.com', 'https://admin.example.com']

app.use(
  '/api/*',
  cors({
    origin: (origin) => {
      return allowedOrigins.includes(origin) ? origin : ''
    },
    credentials: true,
  }),
)
```

## 注册顺序

CORS 应该在业务路由之前注册：

```ts
app.use('/api/*', cors())

app.get('/api/users', (c) => {
  return c.json([])
})
```

如果 CORS 注册太晚，浏览器的预检请求可能无法得到正确响应。

## 常见问题

| 问题 | 原因与处理 |
| --- | --- |
| 浏览器提示 CORS 错误 | 检查 `origin`、方法、请求头是否被允许。 |
| 携带 Cookie 失败 | 需要 `credentials: true`，前端请求也要设置 `credentials`。 |
| 预检请求失败 | 确认 CORS 中间件注册在路由前面。 |
| 本地开发正常，线上失败 | 检查线上域名是否加入允许列表。 |

不要在生产环境随意使用 `origin: '*'` 加凭证请求。公开 API 可以放宽来源，后台管理、用户态接口应该明确来源。
