コンテキスト
リクエストごとに 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) => {
// Set HTTP status code
c.status(201)
return c.text('Your post is created!')
})header()
レスポンスの HTTP ヘッダーを設定できます。
app.get('/', (c) => {
// Set headers
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 the response body
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',
})
})このレスポンスは、以下の Response オブジェクトと同じです。
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()
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 object
app.use('/', async (c, next) => {
await next()
c.res.headers.append('X-Debug', 'Debug message')
})set() / get()
任意のキーと値の組を取得・設定します。有効期間は現在のリクエスト内です。これにより、ミドルウェア間や、ミドルウェアからルートハンドラーへ特定の値を渡せます。
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 のコンストラクターに渡すと、型安全になります。
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 にアクセスできます。
// ExecutionContext object
app.get('/foo', async (c) => {
c.executionCtx.waitUntil(c.env.KV.put(key, data))
// ...
})ExecutionContext には exports フィールドもあります。Wrangler が生成した型で自動補完を利用するには、モジュール拡張を使用できます。
import 'hono'
declare module 'hono' {
interface ExecutionContext {
readonly exports: Cloudflare.Exports
}
}event
Cloudflare Workers 固有の FetchEvent にアクセスできます。これは「Service Worker」構文で使われていましたが、現在は推奨されていません。
// Type definition to make type inference
type Bindings = {
MY_KV: KVNamespace
}
const app = new Hono<{ Bindings: Bindings }>()
// FetchEvent object (only set when using Service Worker syntax)
app.get('/foo', async (c) => {
c.event.waitUntil(c.env.MY_KV.put(key, data))
// ...
})env
Cloudflare Workers では、Worker に関連付けられた環境変数、シークレット、KV 名前空間、D1 データベース、R2 バケットなどをバインディングと呼びます。 種類を問わず、バインディングは常にグローバル変数として利用でき、コンテキストの c.env.BINDING_KEY からアクセスできます。
// Type definition to make type inference
type Bindings = {
MY_KV: KVNamespace
}
const app = new Hono<{ Bindings: Bindings }>()
// Environment object for Cloudflare Workers
app.get('/', async (c) => {
c.env.MY_KV.get('my-key')
// ...
})error
ハンドラーがエラーをスローすると、そのエラーオブジェクトが c.error に格納されます。 ミドルウェア内からアクセスできます。
app.use(async (c, next) => {
await next()
if (c.error) {
// do something...
}
})ContextVariableMap
注意
ContextVariableMap は、変数を設定するミドルウェアが実際に実行されたかどうかにかかわらず、すべてのコンテキストにグローバルに型を追加します。そのため、ミドルウェアが登録されていないハンドラーでも c.get('result') が型安全に見え、実行時の undefined による不具合を隠してしまう可能性があります。
以下の例をご覧ください。
declare module 'hono' {
interface ContextVariableMap {
result: string
}
}
const mw = createMiddleware(async (c, next) => {
c.set('result', 'some values')
await next()
})
const app = new Hono()
// handler uses the middleware
app.get('/foo', mw, (c) => {
const val = c.get('result') // ✅ val is a string and typed as such, as expected
})
// handler doesn't use the middleware
app.get('/bar', (c) => {
const val = c.get('result') // ❌ val is undefined but typed as a string, which can lead to runtime errors
})ContextVariableMap インターフェースを拡張すると、アプリ全体のコンテキスト変数の型をグローバルに定義できます。アプリ全体に適用されるミドルウェアで設定され、コンテキスト内に必ず存在する変数に適しています。
たとえば、次のように定義します。
declare module 'hono' {
interface ContextVariableMap {
result: string
}
}その後、ミドルウェア内で利用できます。
const mw = createMiddleware(async (c, next) => {
c.set('result', 'some values') // result is a string
await next()
})ハンドラー内では、変数が正しい型として推論されます。
app.get('/', (c) => {
const val = c.get('result') // val is a string
// ...
return c.json({ result: val })
})