Zum Inhalt springen

Routing ​

Das Routing von Hono ist flexibel und intuitiv. Sehen wir es uns an.

Grundlagen ​

ts
// HTTP Methods
app
.
get
('/', (
c
) =>
c
.
text
('GET /'))
app
.
post
('/', (
c
) =>
c
.
text
('POST /'))
app
.
put
('/', (
c
) =>
c
.
text
('PUT /'))
app
.
delete
('/', (
c
) =>
c
.
text
('DELETE /'))
app
.
query
('/', (
c
) =>
c
.
text
('QUERY /'))
// Wildcard
app
.
get
('/wild/*/card', (
c
) => {
return
c
.
text
('GET /wild/*/card')
}) // Any HTTP methods
app
.
all
('/hello', (
c
) =>
c
.
text
('Any Method /hello'))
// Custom HTTP method
app
.
on
('PURGE', '/cache', (
c
) =>
c
.
text
('PURGE Method /cache'))
// Multiple Method
app
.
on
(['PUT', 'DELETE'], '/post', (
c
) =>
c
.
text
('PUT or DELETE /post')
) // Multiple Paths
app
.
on
('GET', ['/hello', '/ja/hello', '/en/hello'], (
c
) =>
c
.
text
('Hello')
)

Pfadparameter ​

ts
app
.
get
('/user/:name', async (
c
) => {
const
name
=
c
.
req
.
param
('name')
// ... })

Oder alle Parameter auf einmal:

ts
app
.
get
('/posts/:id/comment/:comment_id', async (
c
) => {
const {
id
,
comment_id
} =
c
.
req
.
param
()
// ... })

Optionale Parameter ​

ts
// Will match `/api/animal` and `/api/animal/:type`
app
.
get
('/api/animal/:type?', (
c
) =>
c
.
text
('Animal!'))

Reguläre Ausdrücke ​

ts
app
.
get
('/post/:date{[0-9]+}/:title{[a-z]+}', async (
c
) => {
const {
date
,
title
} =
c
.
req
.
param
()
// ... })

Pfade mit Schrägstrichen ​

ts
app
.
get
('/posts/:filename{.+\\.png}', async (
c
) => {
//... })

Verkettete Routen ​

ts
app
.
get
('/endpoint', (
c
) => {
return
c
.
text
('GET /endpoint')
}) .
post
((
c
) => {
return
c
.
text
('POST /endpoint')
}) .
delete
((
c
) => {
return
c
.
text
('DELETE /endpoint')
})

Gruppierung ​

Mit einer Hono-Instanz kannst du Routen gruppieren und sie mit der Methode route zur Hauptanwendung hinzufügen.

ts
const 
book
= new
Hono
()
book
.
get
('/', (
c
) =>
c
.
text
('List Books')) // GET /book
book
.
get
('/:id', (
c
) => {
// GET /book/:id const
id
=
c
.
req
.
param
('id')
return
c
.
text
('Get Book: ' +
id
)
})
book
.
post
('/', (
c
) =>
c
.
text
('Create Book')) // POST /book
const
app
= new
Hono
()
app
.
route
('/book',
book
)

Gruppierung ohne Änderung des Basispfads ​

Du kannst mehrere Instanzen auch gruppieren und dabei ihre Basispfade beibehalten.

ts
const 
book
= new
Hono
()
book
.
get
('/book', (
c
) =>
c
.
text
('List Books')) // GET /book
book
.
post
('/book', (
c
) =>
c
.
text
('Create Book')) // POST /book
const
user
= new
Hono
().
basePath
('/user')
user
.
get
('/', (
c
) =>
c
.
text
('List Users')) // GET /user
user
.
post
('/', (
c
) =>
c
.
text
('Create User')) // POST /user
const
app
= new
Hono
()
app
.
route
('/',
book
) // Handle /book
app
.
route
('/',
user
) // Handle /user

Basispfad ​

Du kannst einen Basispfad festlegen.

ts
const 
api
= new
Hono
().
basePath
('/api')
api
.
get
('/book', (
c
) =>
c
.
text
('List Books')) // GET /api/book

Routing anhand des Hostnamens ​

Auch Routen, die einen Hostnamen enthalten, funktionieren.

ts
const 
app
= new
Hono
({
getPath
: (
req
) =>
req
.
url
.
replace
(/^https?:\/([^?]+).*$/, '$1'),
})
app
.
get
('/www1.example.com/hello', (
c
) =>
c
.
text
('hello www1'))
app
.
get
('/www2.example.com/hello', (
c
) =>
c
.
text
('hello www2'))

Routing anhand des Headers host ​

Wenn du im Konstruktor von Hono die Funktion getPath() festlegst, kannst du den Wert des Headers host für das Routing verwenden.

ts
const 
app
= new
Hono
({
getPath
: (
req
) =>
'/' +
req
.
headers
.
get
('host') +
req
.
url
.
replace
(/^https?:\/\/[^/]+(\/[^?]*).*/, '$1'),
})
app
.
get
('/www1.example.com/hello', (
c
) =>
c
.
text
('hello www1'))
// A following request will match the route: // new Request('http://www1.example.com/hello', { // headers: { host: 'www1.example.com' }, // })

Mit diesem Ansatz kannst du das Routing beispielsweise anhand des Headers User-Agent ändern.

Priorität beim Routing ​

Handler und Middleware werden in der Reihenfolge ihrer Registrierung ausgeführt.

ts
app
.
get
('/book/a', (
c
) =>
c
.
text
('a')) // a
app
.
get
('/book/:slug', (
c
) =>
c
.
text
('common')) // common
GET /book/a ---> `a`
GET /book/b ---> `common`

Sobald ein Handler ausgeführt wird, endet die Verarbeitung.

ts
app
.
get
('*', (
c
) =>
c
.
text
('common')) // common
app
.
get
('/foo', (
c
) =>
c
.
text
('foo')) // foo
GET /foo ---> `common` // foo will not be dispatched

Wenn eine Middleware ausgeführt werden soll, registriere sie vor dem Handler.

ts
app
.
use
(
logger
())
app
.
get
('/foo', (
c
) =>
c
.
text
('foo'))

Wenn du einen Fallback-Handler benötigst, registriere ihn nach den anderen Handlern.

ts
app
.
get
('/bar', (
c
) =>
c
.
text
('bar')) // bar
app
.
get
('*', (
c
) =>
c
.
text
('fallback')) // fallback
GET /bar ---> `bar`
GET /foo ---> `fallback`

Reihenfolge der Gruppierung ​

Beachte, dass Fehler in der Reihenfolge gruppierter Routen leicht übersehen werden. Die Funktion route() übernimmt die gespeicherten Routen des zweiten Arguments, beispielsweise three oder two, und fügt sie den eigenen Routen von two oder app hinzu.

ts
three.get('/hi', (c) => c.text('hi'))
two.route('/three', three)
app.route('/two', two)

export default app

Dies gibt eine Antwort mit dem Statuscode 200 zurück.

GET /two/three/hi ---> `hi`

Bei einer falschen Reihenfolge wird hingegen eine Antwort mit dem Statuscode 404 zurückgegeben.

ts
three
.
get
('/hi', (
c
) =>
c
.
text
('hi'))
app
.
route
('/two',
two
) // `two` does not have routes
two
.
route
('/three',
three
)
export default
app
GET /two/three/hi ---> 404 Not Found

Veröffentlicht unter der MIT-Lizenz.