Routing
Das Routing von Hono ist flexibel und intuitiv. Sehen wir es uns an.
Grundlagen
// 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
app.get('/user/:name', async (c) => {
const name = c.req.param('name')
// ...
})Oder alle Parameter auf einmal:
app.get('/posts/:id/comment/:comment_id', async (c) => {
const { id, comment_id } = c.req.param()
// ...
})Optionale Parameter
// Will match `/api/animal` and `/api/animal/:type`
app.get('/api/animal/:type?', (c) => c.text('Animal!'))Reguläre Ausdrücke
app.get('/post/:date{[0-9]+}/:title{[a-z]+}', async (c) => {
const { date, title } = c.req.param()
// ...
})Pfade mit Schrägstrichen
app.get('/posts/:filename{.+\\.png}', async (c) => {
//...
})Verkettete Routen
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.
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.
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 /userBasispfad
Du kannst einen Basispfad festlegen.
const api = new Hono().basePath('/api')
api.get('/book', (c) => c.text('List Books')) // GET /api/bookRouting anhand des Hostnamens
Auch Routen, die einen Hostnamen enthalten, funktionieren.
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.
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.
app.get('/book/a', (c) => c.text('a')) // a
app.get('/book/:slug', (c) => c.text('common')) // commonGET /book/a ---> `a`
GET /book/b ---> `common`Sobald ein Handler ausgeführt wird, endet die Verarbeitung.
app.get('*', (c) => c.text('common')) // common
app.get('/foo', (c) => c.text('foo')) // fooGET /foo ---> `common` // foo will not be dispatchedWenn eine Middleware ausgeführt werden soll, registriere sie vor dem Handler.
app.use(logger())
app.get('/foo', (c) => c.text('foo'))Wenn du einen Fallback-Handler benötigst, registriere ihn nach den anderen Handlern.
app.get('/bar', (c) => c.text('bar')) // bar
app.get('*', (c) => c.text('fallback')) // fallbackGET /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.
three.get('/hi', (c) => c.text('hi'))
two.route('/three', three)
app.route('/two', two)
export default appDies 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.
three.get('/hi', (c) => c.text('hi'))
app.route('/two', two) // `two` does not have routes
two.route('/three', three)
export default appGET /two/three/hi ---> 404 Not Found