Zum Inhalt springen

Kontext ​

Für jede Anfrage wird ein Context-Objekt erstellt, das bis zur Rückgabe der Antwort erhalten bleibt. Du kannst darin Werte speichern, Header und den gewünschten Statuscode setzen sowie auf HonoRequest- und Response-Objekte zugreifen.

req ​

req ist eine Instanz von HonoRequest. Weitere Informationen findest du unter HonoRequest.

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

status() ​

Mit c.status() kannst du einen HTTP-Statuscode setzen. Standardmäßig ist er 200. Für den Statuscode 200 musst du c.status() nicht aufrufen.

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

Du kannst HTTP-Header für die Antwort setzen.

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

body() ​

Gibt eine HTTP-Antwort zurück.

Info

Hinweis: Für Text oder HTML wird die Verwendung von c.text() beziehungsweise c.html() empfohlen.

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

Du kannst auch Folgendes schreiben.

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

Die Antwort entspricht dem folgenden Response-Objekt.

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

text() ​

Gibt Text mit Content-Type: text/plain aus.

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

json() ​

Gibt JSON mit Content-Type: application/json aus.

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

html() ​

Gibt HTML mit Content-Type: text/html aus.

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

notFound() ​

Gibt eine Not Found-Antwort zurück. Du kannst sie mit app.notFound() anpassen.

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

redirect() ​

Leitet um. Der Standardstatuscode ist 302.

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

res ​

Du kannst auf das Response-Objekt zugreifen, das zurückgegeben wird.

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

set() / get() ​

Liest und setzt beliebige Schlüssel-Wert-Paare, die für die Dauer der aktuellen Anfrage bestehen bleiben. So kannst du bestimmte Werte zwischen Middleware-Komponenten oder von Middleware an Routenhandler weitergeben.

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
}"`)
})

Übergib Variables als generischen Typ an den Konstruktor von Hono, um Typsicherheit zu gewährleisten.

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

Werte aus c.set / c.get bleiben nur innerhalb derselben Anfrage erhalten. Sie können nicht zwischen verschiedenen Anfragen geteilt oder dauerhaft gespeichert werden.

var ​

Du kannst auf den Wert einer Variablen auch über c.var zugreifen.

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

Wenn du eine Middleware mit einer eigenen Methode erstellen möchtest, schreibe Folgendes:

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!'))
})

Wenn du die Middleware in mehreren Handlern verwenden möchtest, kannst du app.use() nutzen. Dann musst du Env als generischen Typ an den Konstruktor von Hono übergeben, um Typsicherheit zu gewährleisten.

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

render() / setRenderer() ​

Innerhalb einer eigenen Middleware kannst du mit c.setRenderer() ein Layout festlegen.

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

Anschließend kannst du mit c.render() Antworten innerhalb dieses Layouts erstellen.

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

Die Ausgabe sieht folgendermaßen aus:

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

Darüber hinaus lassen sich die Argumente dieser Funktion flexibel anpassen. Um Typsicherheit zu gewährleisten, kannst du die Typen so definieren:

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

Hier ist ein Beispiel für die Verwendung:

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 ​

Du kannst auf den spezifischen ExecutionContext von Cloudflare Workers zugreifen.

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

Der ExecutionContext besitzt außerdem das Feld exports. Für automatische Vervollständigung mit den von Wrangler erzeugten Typen kannst du eine Modulerweiterung verwenden:

ts
import 'hono'

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

event ​

Du kannst auf das spezifische FetchEvent von Cloudflare Workers zugreifen. Es wurde in der „Service Worker“-Syntax verwendet, die inzwischen nicht mehr empfohlen wird.

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 ​

In Cloudflare Workers werden Umgebungsvariablen, Secrets, KV-Namespaces, D1-Datenbanken, R2-Buckets und weitere Ressourcen, die mit einem Worker verbunden sind, als Bindings bezeichnet. Unabhängig vom Typ sind Bindings immer als globale Variablen verfügbar. Auf sie kann über den Kontext c.env.BINDING_KEY zugegriffen werden.

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 ​

Wenn ein Handler einen Fehler auslöst, wird das Fehlerobjekt in c.error abgelegt. Du kannst in deiner Middleware darauf zugreifen.

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

ContextVariableMap ​

Achtung

ContextVariableMap ergänzt die Typen global für alle Kontexte, unabhängig davon, ob die Middleware, die die Variable setzt, tatsächlich ausgeführt wurde. Dadurch erscheint c.get('result') sogar in Handlern typsicher, in denen deine Middleware nie registriert wurde. Das kann Fehler durch undefined zur Laufzeit verbergen.

Sieh dir das folgende Beispiel an:

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
})

Du kannst die Schnittstelle ContextVariableMap erweitern, um die Typen von Kontextvariablen global für deine gesamte Anwendung zu definieren. Das eignet sich für Variablen, die von einer anwendungsweit eingesetzten Middleware gesetzt werden und garantiert im Kontext vorhanden sind.

Zum Beispiel:

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

Anschließend kannst du dies in deiner Middleware verwenden:

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

In einem Handler wird für die Variable der richtige Typ abgeleitet:

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

Veröffentlicht unter der MIT-Lizenz.