honojs / hono

Web framework built on Web Standards
https://hono.dev
MIT License
17.18k stars 485 forks source link

Handling empty slash slots in URL (Double slash) #3034

Open movahhedi opened 3 weeks ago

movahhedi commented 3 weeks ago

What version of Hono are you using?

4.4.5

What runtime/platform is your app running on?

Node

What steps can reproduce the bug?

Opening a URL on Hono with a double slash, like http://localhost:3001/api//account. It doesn't find the route at /api/account.

What is the expected behavior?

I expect the // to be normalized to /.

What do you see instead?

No response

Additional information

It can be solved with a RegEx like:

Find: /\/+/g Replace: /

OR

Find: /\/{2,}/g Replace: /

yusukebe commented 3 weeks ago

Hi @movahhedi

The router separates paths with /, so supporting it on the routers will be hard. But you can use getPath() function:

https://hono.dev/docs/api/routing#routing-with-hostname

@usualoma Any thoughts?

usualoma commented 3 weeks ago

I am aware that some frameworks treat consecutive "/" as a single "/", but others do not. I, too, think that in Hono, users can deal with getPath(), so there is no need to change the functionality.

movahhedi commented 3 weeks ago

We may be able to remove the extra /s before reaching the routers.

We can also make this optional, which can be set like this:

const hono = new Hono<IHonoEnv>({
    strict: true,
    removeEmptySlots: true,
})

Nevertheless, It can be a functionality of strict: false. So if it's false, it removes the extra /s, and if it's true, it doesn't.

yusukebe commented 2 weeks ago

@movahhedi

As mentioned above, we don't have to add a new function. You can use getPath option. Try the following:

import { Hono } from 'hono'
import { getPath } from 'hono/utils/url'

const app = new Hono({
  getPath: (request) => {
    const path = getPath(request)
    return path.replace(/\/+/g, '/')
  },
})

app.get('/api/account', (c) => c.text('/api/account'))

const res = await app.request('/api//account')
console.log(res.status) // 200