Last Updated: 3/11/2026
Routing
Hono’s routing is flexible and intuitive. It supports path parameters, wildcards, regular expressions, and route grouping.
Basic Routing
HTTP Methods
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('GET /'))
app.post('/', (c) => c.text('POST /'))
app.put('/', (c) => c.text('PUT /'))
app.delete('/', (c) => c.text('DELETE /'))All Methods
app.all('/hello', (c) => c.text('Any Method /hello'))Custom Methods
app.on('PURGE', '/cache', (c) => c.text('PURGE Method /cache'))Multiple Methods or Paths
app.on(['PUT', 'DELETE'], '/post', (c) =>
c.text('PUT or DELETE /post')
)
app.on('GET', ['/hello', '/ja/hello', '/en/hello'], (c) =>
c.text('Hello')
)Path Parameters
Capture dynamic values from the URL:
app.get('/user/:name', (c) => {
const name = c.req.param('name')
return c.text(`Hello, ${name}!`)
})Get all parameters at once:
app.get('/posts/:id/comment/:comment_id', (c) => {
const { id, comment_id } = c.req.param()
return c.json({ id, comment_id })
})Optional Parameters
// Matches /api/animal and /api/animal/:type
app.get('/api/animal/:type?', (c) => c.text('Animal!'))Wildcards
app.get('/wild/*/card', (c) => {
return c.text('GET /wild/*/card')
})Regular Expressions
Use regex patterns for parameters:
app.get('/post/:date{[0-9]+}/:title{[a-z]+}', (c) => {
const { date, title } = c.req.param()
return c.json({ date, title })
})Including Slashes
app.get('/posts/:filename{.+\\.png}', (c) => {
const filename = c.req.param('filename')
return c.text(`Filename: ${filename}`)
})Chained Routes
Chain multiple methods on the same path:
app
.get('/endpoint', (c) => c.text('GET /endpoint'))
.post((c) => c.text('POST /endpoint'))
.delete((c) => c.text('DELETE /endpoint'))Grouping Routes
Group routes using separate Hono instances:
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)Grouping Without Changing Base
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 /userBase Path
Set a base path for all routes:
const api = new Hono().basePath('/api')
api.get('/book', (c) => c.text('List Books')) // GET /api/bookRouting Priority
Handlers execute in registration order:
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`Once a handler is executed, the process stops:
app.get('*', (c) => c.text('common')) // common
app.get('/foo', (c) => c.text('foo')) // foo - never reachedGET /foo ---> `common` // foo will not be dispatchedMiddleware Before Handlers
Place middleware before handlers:
import { logger } from 'hono/logger'
app.use(logger())
app.get('/foo', (c) => c.text('foo'))Fallback Handlers
Place fallback handlers last:
app.get('/bar', (c) => c.text('bar')) // bar
app.get('*', (c) => c.text('fallback')) // fallbackGET /bar ---> `bar`
GET /foo ---> `fallback`Routing with Hostname
Route based on hostname:
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 with Host Header
Route based on the Host header:
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'))Next Steps
Learn about handling requests and responses with Context & Request.