Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions docs/api/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,20 @@ app.get('/api/animal/:type?', (c) => c.text('Animal!'))

## Regexp

You can apply a Regular Expression to a path parameter. The syntax is `/:paramName{regexp}`.

```ts twoslash
import { Hono } from 'hono'
const app = new Hono()
// ---cut---
// Example: :date must be a sequence of digits ([0-9]+),
// and :title must be a sequence of lowercase letters ([a-z]+).
app.get('/post/:date{[0-9]+}/:title{[a-z]+}', async (c) => {
const { date, title } = c.req.param()
// ^?
// e.g. /post/2025/my-post -> date = "2025", title = "my-post" (if [a-z-]+)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the explanation of "my-post" with [a-z-]+ is not necessary. It's just about regexp syntax. So only the following is needed:

e.g. /post/2025/mypost -> date = "2025", title = "mypost"

// Note: for "my-post", the regex should be `[a-z-]+`
// For the original `[a-z]+`: /post/2025/mypost -> date = "2025", title = "mypost"
// ...
})
```
Expand All @@ -92,8 +99,17 @@ app.get('/post/:date{[0-9]+}/:title{[a-z]+}', async (c) => {
import { Hono } from 'hono'
const app = new Hono()
// ---cut---
app.get('/posts/:filename{.+\\.png}', async (c) => {
//...
// Example: :filename must end with .png and have a non-empty name part.
// The regex `.+\\.png$` ensures this:
// - `.+` matches one or more leading characters (the filename base).
// - `\\.png$` matches the literal ".png" string at the end of the segment.
//
// This means paths like /file/dog.png will match, making filename "data.png".
// Paths like /file/.png (empty name part) or /file/data.png.txt (wrong suffix) will not match.
app.get('/post/:filename{.+\\.png$}', async (c) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may not be clear that filename can contain /. For example, make the app as follows:

app.get('/file/:filename{.+\\.png$}', async (c) => {
  const { filename } = c.req.param()
  // ...
})

And explain that accessing /file/foo/bar.png will make filename be foo/bar.png. How about it?

const { filename } = c.req.param()
// ^?
// ...
})
```

Expand Down