Context
Context 对象在每次请求时都会被实例化,并在返回响应之前保持有效。你可以在其中存储值、设置响应头和状态码,还可以访问 HonoRequest 和 Response 对象。
req
req 是 HonoRequest 的实例。更多详情见 HonoRequest。
app.get('/hello', (c) => {const userAgent = c.req.header('User-Agent')// ...})
status()
使用 c.status() 设置 HTTP 状态码,默认是 200。如果状态码是 200,就不需要显式调用 c.status()。
app.post('/posts', (c) => {// 设置 HTTP 状态码c.status(201)return c.text('Your post is created!')})
header()
用 c.header() 为响应设置 HTTP Headers。
app.get('/', (c) => {// 设置响应头c.header('X-Message', 'My custom message')return c.text('HellO!')})
body()
返回 HTTP 响应。
提示:
当返回文本或 HTML 时,推荐使用 c.text() 或 c.html()。
app.get('/welcome', (c) => {c.header('Content-Type', 'text/plain')// 返回响应内容return c.body('Thank you for coming')})
也可以这样写:
app.get('/welcome', (c) => {return c.body('Thank you for coming', 201, {'X-Message': 'Hello!','Content-Type': 'text/plain',})})
等价于:
new Response('Thank you for coming', {status: 201,headers: {'X-Message': 'Hello!','Content-Type': 'text/plain',},})
text()
以 Content-Type:text/plain 渲染纯文本。
app.get('/say', (c) => {return c.text('Hello!')})
json()
以 Content-Type:application/json 渲染 JSON。
app.get('/api', (c) => {return c.json({ message: 'Hello!' })})
html()
以 Content-Type:text/html 渲染 HTML。
app.get('/', (c) => {return c.html('<h1>Hello! Hono!</h1>')})
notFound()
返回一个 404 Not Found 响应。可以通过 app.notFound() 自定义。
app.get('/notfound', (c) => {return c.notFound()})
redirect()
执行重定向,默认状态码是 302。
app.get('/redirect', (c) => {return c.redirect('/')})app.get('/redirect-permanently', (c) => {return c.redirect('/', 301)})
res
可以访问即将返回的 Response 对象。
// Response 对象app.use('/', async (c, next) => {await next()c.res.headers.append('X-Debug', 'Debug message')})
set() / get()
通过 c.set 和 c.get 设置和获取任意的 key-value 对,生命周期仅限当前请求。这样可以在中间件与路由处理器之间传递值。
app.use(async (c, next) => {c.set('message', 'Hono is cool!!')await next()})app.get('/', (c) => {const message = c.get('message')return c.text(`The message is "${message}"`)})
如果想让类型更安全,可以把 Variables 类型传入 Hono 构造函数的 Generics 中。
type Variables = {message: string}const app = new Hono<{ Variables: Variables }>()
注意:
c.set / c.get 的值只在同一请求内有效,不能跨请求共享或持久化。
var
你也可以用 c.var 访问变量。
const result = c.var.client.oneMethod()
如果想在中间件中提供自定义方法,可以这样写:
type Env = {Variables: {echo: (str: string) => string}}const app = new Hono()const echoMiddleware = createMiddleware<Env>(async (c, next) => {c.set('echo', (str) => str)await next()})app.get('/echo', echoMiddleware, (c) => {return c.text(c.var.echo('Hello!'))})
如果要在多个路由中复用该中间件,可以用 app.use(),并将 Env 类型传入 Hono 构造函数:
const app = new Hono<Env>()app.use(echoMiddleware)app.get('/echo', (c) => {return c.text(c.var.echo('Hello!'))})
render() / setRenderer()
可以通过 c.setRenderer() 设置一个渲染布局。
app.use(async (c, next) => {c.setRenderer((content) => {return c.html(<html><body><p>{content}</p></body></html>)})await next()})
然后使用 c.render() 在该布局内渲染内容:
app.get('/', (c) => {return c.render('Hello!')})
输出结果为:
<html><body><p>Hello!</p></body></html>
你还可以自定义参数类型,例如:
declare module 'hono' {interface ContextRenderer {(content: string | Promise<string>,head: { title: string }): Response | Promise<Response>}}
使用示例:
app.use('/pages/*', async (c, next) => {c.setRenderer((content, head) => {return c.html(<html><head><title>{head.title}</title></head><body><header>{head.title}</header><p>{content}</p></body></html>)})await next()})app.get('/pages/my-favorite', (c) => {return c.render(<p>Ramen and Sushi</p>, {title: 'My favorite',})})app.get('/pages/my-hobbies', (c) => {return c.render(<p>Watching baseball</p>, {title: 'My hobbies',})})
executionCtx
可访问 Cloudflare Workers 特有的 ExecutionContext。
app.get('/foo', async (c) => {c.executionCtx.waitUntil(c.env.KV.put(key, data))// ...})
event
可访问 Cloudflare Workers 的 FetchEvent(早期 Service Worker 语法),但不再推荐。
type Bindings = {MY_KV: KVNamespace}const app = new Hono<{ Bindings: Bindings }>()// FetchEvent 对象(仅在 Service Worker 语法时可用)app.get('/foo', async (c) => {c.event.waitUntil(c.env.MY_KV.put(key, data))// ...})
env
Cloudflare Workers 的环境变量、密钥、KV、D1 数据库、R2 存储桶等被称为 bindings,可以通过 c.env.BINDING_KEY 访问。
type Bindings = {MY_KV: KVNamespace}const app = new Hono<{ Bindings: Bindings }>()app.get('/', async (c) => {c.env.MY_KV.get('my-key')// ...})
error
如果处理器抛出错误,错误对象会被放入 c.error,可以在中间件中访问。
app.use(async (c, next) => {await next()if (c.error) {// 处理错误}})
ContextVariableMap
如果你想在中间件中扩展变量的类型定义,可以扩展 ContextVariableMap。
declare module 'hono' {interface ContextVariableMap {result: string}}
然后在中间件中使用:
const mw = createMiddleware(async (c, next) => {c.set('result', 'some values') // result 是 stringawait next()})
在处理器中,类型也会自动推断:
app.get('/', (c) => {const val = c.get('result') // val 是 stringreturn c.json({ result: val })})
