360 Secure SkillHub
360 安全技能中心

hono

提供 Hono Web 框架的开发参考资料,包含核心 API、路由、中间件、Zod 校验、RPC 客户端、JSX、上下文扩展与测试方法,并给出项目创建命令和大型应用结构建议,适用于跨 JavaScript 运行时构建 API。

yuexiaoliang
yuexiaoliang
热度 41.66
最近更新 2026-05-11 17:42:41
分类:开发依赖:代码执行应用场景:代码生成 / API 集成 / 模板

安装技能

复制下面的话术发给你的 Agent,它会通过 secure-skills 检索并安装该技能。

执行命令安装此 skill: npx secure-skills-cli add hono
Metadata
name
hono
description
Hono web framework skill for building APIs across all JS runtimes (Cloudflare Workers, Deno, Bun, Node.js, etc.). Covers routing, middleware, JSX, RPC client, Zod validation, and context extensions.
metadata
{"author":"yuexiaoliang","version":"1.0.0"}

Hono

Hono (Japanese for "flame" 🔥) is a small, fast web framework built on Web Standards. Works on all JS runtimes.

Core API

import { Hono } from 'hono'
const app = new Hono()

app.get('/', (c) => c.text('Hello!'))
app.post('/api', async (c) => c.json({ ok: true }, 201))

export default app

Context Core Methods

// Responses
c.text(str, status?)       // plain text
c.json(obj, status?)        // JSON
c.html(str)                 // HTML string
c.body(stream, headers?)    // raw body

// Requests
c.req.param('id')          // path params (type-inferred)
c.req.query('name')         // query params
c.req.valid('json')         // validated data (with validator)
c.req.header('x-token')     // request headers
c.req.cookie('session')     // cookies

// Variables/state
c.set('key', value)         // set variable (shared via middleware)
c.get('key')                // get variable
c.var.foo                   // access middleware-set variable

// Other
c.notFound()                // 404 (avoid in RPC)
c.redirect('/path', 302)    // redirect

Routing

// Basic routes
app.get('/users/:id', (c) => c.json({ id: c.req.param('id') }))

// Regex routes
app.get('/posts/:id{.+}', (c) => { /* matches /posts/a/b/c */ })

// Route grouping
const api = new Hono()
api.get('/posts', ...)
api.get('/users', ...)
app.route('/api', api)

// HTTP methods
app.get|post|put|patch|delete|options|head

// Multiple paths
app.get(['/home', '/'], (c) => c.text('Home'))

Project Creation

# npm
npm create hono@latest my-app -- --template cloudflare-workers --pm npm --install

# bun
bun create hono@latest my-app

# Common templates: cloudflare-workers, bun, deno, vercel, aws-lambda, nodejs

npm create arg passing: npm requires --, others optional. --template selects template, --pm specifies package manager, --install auto-installs deps.

Large Application Structure

Recommended: Use app.route() for modular apps, not RoR-style Controllers (type inference breaks).

// authors.ts - separate Hono instance per module
const app = new Hono()
  .get('/', (c) => c.json('list'))
  .post('/', (c) => c.json('create', 201))
  .get('/:id', (c) => c.json(c.req.param('id')))

export default app
export type AppType = typeof app
// index.ts - compose
import authors from './authors'
const app = new Hono()
app.route('/authors', authors)
export default app

RPC: Chain methods to export types:

const route = app.get('/', (c) => c.json({ ok: true }))
export type AppType = typeof route  // or typeof app

Middleware

// Built-in
import { cors, logger, etag } from 'hono/middleware'
app.use('*', cors(), logger(), etag())

// Custom
app.use('*', async (c, next) => {
  c.set('requestId', crypto.randomUUID())
  await next()
})

// Path-specific
app.use('/api/*', authenticate())

// Error handling
app.onError((err, c) => {
  return c.json({ error: err.message }, 500)
})

Common built-in middleware: cors, jwt, bearer-auth, basic-auth, logger, etag, secure-headers, cache, compress, body-limit, pretty-json, timing, request-id, ip-restriction

Validators

import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

app.post('/posts',
  zValidator('json', z.object({ title: z.string(), body: z.string() })),
  (c) => {
    const { title, body } = c.req.valid('json')
    return c.json({ ok: true }, 201)
  }
)

export type AppType = typeof app  // export for client

Validation targets: json, form, query, param, header, cookie

RPC Client

import { hc } from 'hono/client'
import type { AppType } from './server'

const client = hc<AppType>('http://localhost:8787/')

// Request
const res = await client.posts.$post({
  json: { title: 'Hello', body: 'Hono!' }
})

// Response
if (res.ok) {
  const data = await res.json()
}

Don't use c.notFound() in RPC mode — use c.json(..., 404) instead, or type inference breaks.

Path params use param, queries use query, forms use form, JSON use json.

JSX

import { Hono } from 'hono'
import type { FC } from 'hono/jsx'

const app = new Hono()

const Layout: FC = (props) => (
  <html><body>{props.children}</body></html>
)

app.get('/', (c) => c.html(<Layout><h1>Hello!</h1></Layout>))

tsconfig.json needs:

{
  "compilerOptions": {
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx"
  }
}

Helpers

Helper Purpose
html Template literal HTML
cookie Cookie read/write
jwt JWT encode/decode
ssg Static site generation
streaming Streaming responses
accepts Content negotiation
factory Reusable handlers (preserves type inference)

Context Extensions (Variable Types)

// Define types
type Env = { Variables: { user: User } }

// Use
const app = new Hono<{ Variables: { user: User } }>()

app.use('*', async (c, next) => {
  c.set('user', { id: 1, name: 'Alice' })
  await next()
})

app.get('/me', (c) => c.json(c.var.user))

Testing

// Method 1: app.request()
const res = await app.request('/api/posts?page=1', {
  method: 'POST',
  body: JSON.stringify({ title: 'Hello' }),
  headers: { 'Content-Type': 'application/json' }
})

// Method 2: fetch style
const res = await fetch('/api/posts', {
  method: 'POST',
  body: JSON.stringify({ title: 'Hello' })
})
const data = await res.json()

Reference Docs

Detailed docs loaded on demand: