kriasoft / universal-router

A simple middleware-style router for isomorphic JavaScript web apps
https://www.kriasoft.com/universal-router/
MIT License
1.7k stars 104 forks source link

Provide option for strict routing via path-to-regexp #155

Closed nickspiel closed 6 years ago

nickspiel commented 6 years ago

I'm submitting a ...

I am looking to serve different pages for paths with and without trailing slashes.

Current behaviour:

// Requesting /some-path/
/:var(some-path) // Should not match but does
/:var(some-path)/ // Never gets hit as first route matches

Desired behaviour:

// Requesting /some-path/
/:var(some-path) // Does not match
/:var(some-path)/ // Matches

It looks like universal-router uses the non-strict version of path-to-regexp and there is no option to request strict routing. It would be great to have the option to enable strict mode through the universal-router config option.

frenzzy commented 6 years ago

You can use the right order of routes to reach the same result:

const router = new UniversalRouter([
  { path: '/some-path/', action: () => 'A' },
  { path: '/some-path',  action: () => 'B' },

  // or
  { path: '/other-path', children: [
    { path: '/', action: () => 'C' },
    { path: '',  action: () => 'D' },
  ] },
])

router.resolve('/some-path/')  // => A
router.resolve('/some-path')   // => B

router.resolve('/other-path/') // => C
router.resolve('/other-path')  // => D

Demo: https://codepen.io/frenzzy/pen/MXjrOB?editors=0010

nickspiel commented 6 years ago

Thanks for the reply and example!

Maybe my example is too simple, does it work with named groups?

This is a more accurate reflection of my issue:

const routes = [
  {
    // should match /for-sale/ and /for-sale/abc/xyz etc and does
    path: '/:channel(for-sale|for-lease)/(.*)?',
    action: () => A,
  },
  {
    // should match /for-sale but does not and the A route matches instead
    path: '/:channel(for-sale|for-lease|invest)/(.*)?',
    action: () => B,
  },
];
nickspiel commented 6 years ago

Okay - it was my mistake my A route needed to be /:channel(for-sale|for-lease)(/.*).

Thanks for the assistance and for the awesome project!

Closing.