> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
> Use this file to discover all available pages before exploring further.

# Routing

> Learn how routing works in Hono, including route definition, HTTP methods, path patterns, and route matching.

## Overview

Routing in Hono maps HTTP requests to handler functions based on the request method and URL path. Hono provides a simple and intuitive API for defining routes with full type safety.

## Defining Routes

Routes are defined using HTTP method helpers on the Hono application instance. Each method corresponds to a standard HTTP verb.

### Basic Route Definition

```typescript theme={null}
import { Hono } from 'hono'

const app = new Hono()

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

app.post('/posts', (c) => {
  return c.json({ message: 'Post created' })
})
```

## HTTP Method Handlers

Hono supports all standard HTTP methods through dedicated handler functions:

```typescript theme={null}
app.get('/users', (c) => c.text('GET /users'))
app.post('/users', (c) => c.text('POST /users'))
app.put('/users/:id', (c) => c.text('PUT /users/:id'))
app.delete('/users/:id', (c) => c.text('DELETE /users/:id'))
app.patch('/users/:id', (c) => c.text('PATCH /users/:id'))
app.options('/users', (c) => c.text('OPTIONS /users'))
```

### Available Methods

From `src/hono-base.ts:104-110`:

```typescript theme={null}
get!: HandlerInterface<E, 'get', S, BasePath, CurrentPath>
post!: HandlerInterface<E, 'post', S, BasePath, CurrentPath>
put!: HandlerInterface<E, 'put', S, BasePath, CurrentPath>
delete!: HandlerInterface<E, 'delete', S, BasePath, CurrentPath>
options!: HandlerInterface<E, 'options', S, BasePath, CurrentPath>
patch!: HandlerInterface<E, 'patch', S, BasePath, CurrentPath>
all!: HandlerInterface<E, 'all', S, BasePath, CurrentPath>
```

### The `all` Method

The `all` method matches any HTTP method:

```typescript theme={null}
app.all('/api/*', (c) => {
  return c.text('Matches all methods')
})
```

## Path Patterns

Hono supports various path patterns for flexible route matching.

### Static Paths

Exact path matching:

```typescript theme={null}
app.get('/about', (c) => c.text('About page'))
app.get('/contact', (c) => c.text('Contact page'))
```

### Path Parameters

Capture dynamic segments using `:param` syntax:

```typescript theme={null}
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ userId: id })
})

app.get('/posts/:postId/comments/:commentId', (c) => {
  const { postId, commentId } = c.req.param()
  return c.json({ postId, commentId })
})
```

### Wildcard Paths

Match multiple path segments:

```typescript theme={null}
app.get('/files/*', (c) => {
  return c.text('Matches /files/any/path/here')
})
```

## The `on` Method

For custom methods or matching multiple methods, use the `on` method:

```typescript theme={null}
// Single method
app.on('CUSTOM', '/webhook', (c) => {
  return c.text('Custom method handler')
})

// Multiple methods
app.on(['GET', 'POST'], '/dual', (c) => {
  return c.text(`Handled ${c.req.method}`)
})

// Multiple paths
app.on('GET', ['/path1', '/path2'], (c) => {
  return c.text('Multiple paths')
})
```

From `src/hono-base.ts:144-154`:

```typescript theme={null}
this.on = (method: string | string[], path: string | string[], ...handlers: H[]) => {
  for (const p of [path].flat()) {
    this.#path = p
    for (const m of [method].flat()) {
      handlers.map((handler) => {
        this.#addRoute(m.toUpperCase(), this.#path, handler)
      })
    }
  }
  return this as any
}
```

## Route Grouping

Group routes with a common base path using `route`:

```typescript theme={null}
const api = new Hono()
api.get('/users', (c) => c.json({ users: [] }))
api.get('/posts', (c) => c.json({ posts: [] }))

const app = new Hono()
app.route('/api', api)
// Now accessible at /api/users and /api/posts
```

From `src/hono-base.ts:208-232`:

<CodeGroup>
  ```typescript Route Method theme={null}
  route<
    SubPath extends string,
    SubEnv extends Env,
    SubSchema extends Schema,
    SubBasePath extends string,
    SubCurrentPath extends string,
  >(
    path: SubPath,
    app: Hono<SubEnv, SubSchema, SubBasePath, SubCurrentPath>
  ): Hono<E, MergeSchemaPath<SubSchema, MergePath<BasePath, SubPath>> | S, BasePath, CurrentPath>
  ```
</CodeGroup>

## Base Paths

Define a base path for all routes in an instance:

```typescript theme={null}
const api = new Hono().basePath('/api/v1')

api.get('/users', (c) => c.text('GET /api/v1/users'))
api.get('/posts', (c) => c.text('GET /api/v1/posts'))
```

From `src/hono-base.ts:247-253`:

```typescript theme={null}
basePath<SubPath extends string>(
  path: SubPath
): Hono<E, S, MergePath<BasePath, SubPath>, MergePath<BasePath, SubPath>> {
  const subApp = this.#clone()
  subApp._basePath = mergePath(this._basePath, path)
  return subApp
}
```

## Route Matching

Routes are matched in the order they are defined. The first matching route handles the request.

### Strict Mode

By default, Hono uses strict mode which distinguishes `/path` from `/path/`:

```typescript theme={null}
const app = new Hono({ strict: true }) // default

app.get('/users', handler) // Matches /users only
app.get('/posts/', handler) // Matches /posts/ only
```

Disable strict mode to treat both the same:

```typescript theme={null}
const app = new Hono({ strict: false })

app.get('/users', handler) // Matches both /users and /users/
```

From `src/hono-base.ts:46-87`:

<CodeGroup>
  ```typescript Hono Options theme={null}
  type HonoOptions<E extends Env> = {
    /**
     * `strict` option specifies whether to distinguish whether the last path is a directory or not.
     *
     * @default true
     */
    strict?: boolean
    /**
     * `router` option specifies which router to use.
     */
    router?: Router<[H, RouterRoute]>
    /**
     * `getPath` can handle the host header value.
     */
    getPath?: GetPath<E>
  }
  ```
</CodeGroup>

## Chaining Routes

Multiple handlers can be chained on the same path:

```typescript theme={null}
app
  .get('/users', (c) => c.json({ message: 'Getting users' }))
  .post('/users', (c) => c.json({ message: 'Creating user' }))
  .put('/users/:id', (c) => c.json({ message: 'Updating user' }))
```

From `src/hono-base.ts:127-141`, routes return the app instance for chaining:

```typescript theme={null}
allMethods.forEach((method) => {
  this[method] = (args1: string | H, ...args: H[]) => {
    if (typeof args1 === 'string') {
      this.#path = args1
    } else {
      this.#addRoute(method, this.#path, args1)
    }
    args.forEach((handler) => {
      this.#addRoute(method, this.#path, handler)
    })
    return this as any
  }
})
```

## Route Information

Access registered routes through the `routes` property:

```typescript theme={null}
const app = new Hono()
app.get('/users', handler)
app.post('/posts', handler)

console.log(app.routes)
// Returns RouterRoute[] with route metadata
```

From `src/types.ts:57-62`:

```typescript theme={null}
interface RouterRoute {
  basePath: string
  path: string
  method: string
  handler: H
}
```

## Best Practices

<Tip>
  * Define specific routes before wildcard routes
  * Use route grouping for better organization
  * Leverage TypeScript for path parameter type safety
  * Use `basePath` for API versioning
</Tip>

<Warning>
  Wildcard routes (`*`) should be defined last, as they will match any path that hasn't been matched by previous routes.
</Warning>

## Related

* [Handlers](/concepts/handlers) - Learn about request handlers
* [Middleware](/concepts/middleware) - Add middleware to routes
* [Context](/concepts/context) - Access request and response data
