lukeed / trouter

:fish: A fast, small-but-mighty, familiar fish...errr, router*
MIT License
641 stars 23 forks source link

Trailing slashes in paths do not result in different routes #25

Open aral opened 4 months ago

aral commented 4 months ago

Use case

I want to have pages on a site that are accessed without a trailing slash forward to the trailing slash version.

Why? To avoid relative URLs to assets in the same folder breaking when the path is missing a trailing slash in the markup (e.g., <script src='./index.js'></script>).

See: https://stackoverflow.com/questions/31111257/relative-links-on-pages-without-trailing-slash

Issue

I can’t add separate handlers for '/foo' and '/foo/'.

import { Trouter } from 'trouter'

const router = new Trouter()

router.get('/foo', () => console.log('/foo'))
router.get('/foo/', () => console.log('/foo/'))

const routeA = router.find('GET', '/foo')
const routeB = router.find('GET', '/foo/')

console.log('Route A (/foo). Handlers:')
routeA.handlers.forEach(fn => fn())

console.log('\nRoute B (/foo/). Handlers:')
routeB.handlers.forEach(fn => fn())

Results in:

Route A (/foo). Handlers:
/foo
/foo/

Route B (/foo/). Handlers:
/foo
/foo/

Whereas I would expect it to result in:

Route A (/foo). Handlers:
/foo

Route B (/foo/). Handlers:
/foo/
aral commented 4 months ago

This comes down to \/? being matched at the end of all patterns in regexparam: https://github.com/aral/regexparam/blob/master/src/index.js#L28

suddjian commented 4 months ago

for reference, the path-to-regexp (and thus Express) handles this by offering a trailing option: https://github.com/pillarjs/path-to-regexp/blob/140b8248e99c34414910d0d2d6c0e822327e1197/src/index.ts#L577