教程 hono tutorial

错误处理

接口错误要同时照顾开发者调试和客户端消费。Hono 提供 app.notFound()、app.onError() 和 HTTPException 等方式处理错误。

404 处理

ts
app.notFound((c) => {
  return c.json(
    {
      message: 'Not Found',
      path: c.req.path,
    },
    404,
  )
})

如果你的服务是纯 API,建议统一返回 JSON。不要让部分接口返回 HTML 404,部分接口返回 JSON 404。

全局错误处理

ts
app.onError((err, c) => {
  console.error(err)

  return c.json(
    {
      message: 'Internal Server Error',
    },
    500,
  )
})

生产环境不要把完整错误堆栈返回给客户端。堆栈应该进入日志或错误追踪系统。

使用 HTTPException

HTTPException 适合在深层函数或中间件中抛出带状态码的错误:

ts
import { HTTPException } from 'hono/http-exception'

app.get('/me', (c) => {
  const token = c.req.header('Authorization')

  if (!token) {
    throw new HTTPException(401, { message: 'Missing token' })
  }

  return c.json({ id: 1 })
})

在 onError 中识别它:

ts
import { HTTPException } from 'hono/http-exception'

app.onError((err, c) => {
  if (err instanceof HTTPException) {
    return err.getResponse()
  }

  console.error(err)
  return c.json({ message: 'Internal Server Error' }, 500)
})

如果需要统一 JSON 格式,可以不直接返回 err.getResponse(),而是读取状态和消息后自行构造响应。

业务错误格式

一个简单稳定的 API 错误格式:

json
{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "用户不存在"
  }
}

对应工具函数:

ts
function errorResponse(c, code: string, message: string, status = 400) {
  return c.json(
    {
      error: { code, message },
    },
    status,
  )
}

使用:

ts
app.get('/users/:id', (c) => {
  const user = null

  if (!user) {
    return errorResponse(c, 'USER_NOT_FOUND', '用户不存在', 404)
  }

  return c.json(user)
})

错误处理建议

  • 客户端输入错误用 400,未登录用 401,无权限用 403,资源不存在用 404。
  • 服务器内部异常用 500,不要为了“请求成功到达”而返回 200。
  • 验证错误要指出字段和原因,但不要泄露安全敏感信息。
  • 统一错误格式,方便前端、客户端 SDK 和监控系统处理。