本文へ移動

コンテキスト ​

リクエストごとに Context オブジェクトが作成され、レスポンスが返されるまで保持されます。値の保存、返却するヘッダーやステータスコードの設定、HonoRequest や Response オブジェクトへのアクセスができます。

req ​

req は HonoRequest のインスタンスです。詳しくは HonoRequest を参照してください。

ts
app
.
get
('/hello', (
c
) => {
const
userAgent
=
c
.
req
.
header
('User-Agent')
// ... })

status() ​

c.status() で HTTP ステータスコードを設定できます。デフォルトは 200 です。ステータスコードが 200 であれば、c.status() を使う必要はありません。

ts
app
.
post
('/posts', (
c
) => {
// Set HTTP status code
c
.
status
(201)
return
c
.
text
('Your post is created!')
})

レスポンスの HTTP ヘッダーを設定できます。

ts
app
.
get
('/', (
c
) => {
// Set headers
c
.
header
('X-Message', 'My custom message')
return
c
.
text
('Hello!')
})

body() ​

HTTP レスポンスを返します。

情報

注意:テキストや HTML を返す場合は、c.text() または c.html() の使用を推奨します。

ts
app
.
get
('/welcome', (
c
) => {
c
.
header
('Content-Type', 'text/plain')
// Return the response body return
c
.
body
('Thank you for coming')
})

以下のように記述することもできます。

ts
app
.
get
('/welcome', (
c
) => {
return
c
.
body
('Thank you for coming', 201, {
'X-Message': 'Hello!', 'Content-Type': 'text/plain', }) })

このレスポンスは、以下の Response オブジェクトと同じです。

ts
new 
Response
('Thank you for coming', {
status
: 201,
headers
: {
'X-Message': 'Hello!', 'Content-Type': 'text/plain', }, })

text() ​

Content-Type: text/plain でテキストを返します。

ts
app
.
get
('/say', (
c
) => {
return
c
.
text
('Hello!')
})

json() ​

Content-Type: application/json で JSON を返します。

ts
app
.
get
('/api', (
c
) => {
return
c
.
json
({
message
: 'Hello!' })
})

html() ​

Content-Type: text/html で HTML を返します。

ts
app
.
get
('/', (
c
) => {
return
c
.
html
('<h1>Hello! Hono!</h1>')
})

notFound() ​

Not Found レスポンスを返します。app.notFound() でカスタマイズできます。

ts
app
.
get
('/notfound', (
c
) => {
return
c
.
notFound
()
})

redirect() ​

リダイレクトします。デフォルトのステータスコードは 302 です。

ts
app
.
get
('/redirect', (
c
) => {
return
c
.
redirect
('/')
})
app
.
get
('/redirect-permanently', (
c
) => {
return
c
.
redirect
('/', 301)
})

res ​

返却される Response オブジェクトにアクセスできます。

ts
// Response object
app
.
use
('/', async (
c
,
next
) => {
await
next
()
c
.
res
.
headers
.
append
('X-Debug', 'Debug message')
})

set() / get() ​

任意のキーと値の組を取得・設定します。有効期間は現在のリクエスト内です。これにより、ミドルウェア間や、ミドルウェアからルートハンドラーへ特定の値を渡せます。

ts
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 のコンストラクターに渡すと、型安全になります。

ts
type 
Variables
= {
message
: string
} const
app
= new
Hono
<{
Variables
:
Variables
}>()

c.set / c.get の値は、同じリクエスト内でのみ保持されます。異なるリクエスト間で共有したり、永続化したりすることはできません。

var ​

c.var から変数の値にアクセスすることもできます。

ts
const 
result
=
c
.
var
.client.oneMethod()

独自のメソッドを提供するミドルウェアを作成する場合は、 以下のように記述します。

ts
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 のコンストラクターに渡す必要があります。

ts
const 
app
= new
Hono
<
Env
>()
app
.
use
(
echoMiddleware
)
app
.
get
('/echo', (
c
) => {
return
c
.
text
(
c
.
var
.
echo
('Hello!'))
})

render() / setRenderer() ​

独自のミドルウェア内で c.setRenderer() を使ってレイアウトを設定できます。

tsx
app
.
use
(async (
c
,
next
) => {
c
.
setRenderer
((
content
) => {
return
c
.
html
(
<
html
>
<
body
>
<
p
>{
content
}</
p
>
</
body
>
</
html
>
) }) await
next
()
})

その後、c.render() を使って、このレイアウト内にレスポンスを作成できます。

ts
app
.
get
('/', (
c
) => {
return
c
.
render
('Hello!')
})

出力は以下のようになります。

html
<html>
  <body>
    <p>Hello!</p>
  </body>
</html>

さらに、この機能では引数を柔軟にカスタマイズできます。 型安全性を確保するには、以下のように型を定義します。

ts
declare module 'hono' {
  interface ContextRenderer {
    (
      content: string | Promise<string>,
      head: { title: string }
    ): Response | Promise<Response>
  }
}

使用例を示します。

ts
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 にアクセスできます。

ts
// ExecutionContext object
app
.
get
('/foo', async (
c
) => {
c
.
executionCtx
.
waitUntil
(
c
.
env
.
KV
.put(
key
,
data
))
// ... })

ExecutionContext には exports フィールドもあります。Wrangler が生成した型で自動補完を利用するには、モジュール拡張を使用できます。

ts
import 'hono'

declare module 'hono' {
  interface ExecutionContext {
    readonly exports: Cloudflare.Exports
  }
}

event ​

Cloudflare Workers 固有の FetchEvent にアクセスできます。これは「Service Worker」構文で使われていましたが、現在は推奨されていません。

ts
// 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 からアクセスできます。

ts
// 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 に格納されます。 ミドルウェア内からアクセスできます。

ts
app
.
use
(async (
c
,
next
) => {
await
next
()
if (
c
.
error
) {
// do something... } })

ContextVariableMap ​

注意

ContextVariableMap は、変数を設定するミドルウェアが実際に実行されたかどうかにかかわらず、すべてのコンテキストにグローバルに型を追加します。そのため、ミドルウェアが登録されていないハンドラーでも c.get('result') が型安全に見え、実行時の undefined による不具合を隠してしまう可能性があります。

以下の例をご覧ください。

ts
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 インターフェースを拡張すると、アプリ全体のコンテキスト変数の型をグローバルに定義できます。アプリ全体に適用されるミドルウェアで設定され、コンテキスト内に必ず存在する変数に適しています。

たとえば、次のように定義します。

ts
declare module 'hono' {
  interface ContextVariableMap {
    result: string
  }
}

その後、ミドルウェア内で利用できます。

ts
const 
mw
=
createMiddleware
(async (
c
,
next
) => {
c
.
set
('result', 'some values') // result is a string
await
next
()
})

ハンドラー内では、変数が正しい型として推論されます。

ts
app
.
get
('/', (
c
) => {
const
val
=
c
.
get
('result') // val is a string
// ... return
c
.
json
({
result
:
val
})
})

MIT ライセンスで公開されています。