Skip to content

Parameters followed by an escaped colon are mis-parsedย #2517

@darkuranium

Description

@darkuranium

Reproduction

https://paths.esm.dev/?p=AAMeJQ2BuMDAFAF2JXAJkhXgAXQAzhugPUAFGBrQSoB0AJln0DVAEgARIKDWCMwAtwdU5FqlITEMcMRpSTgHfQgIKUrpRABA&t=/a/section:abc

Steps to reproduce the bug

There are two related bugs, but seem to be triggered by the same issue (the reproduction link shows both bugs).

  1. Create a route that contains \: immediately following a parameter, e.g. { path: '/:foo([^:]+)\\:abc' }
  2. Attempt to load the route by navigating to (say) section:abc; the attempt will fail (but should succeed)
  3. Attempt to load the route by navigating to (say) sectionabc; the attempt will succeed (but should fail)
  4. Also note that $route.params is incorrect in the above case, containing { 'foo:': ... } instead of { foo: ... } (note the colon)

Expected behavior

A route of /:foo([^:]+)\:abc should:

  • not suffix a ':' to the foo parameter name ($route.params should be { foo: ... } and not { 'foo:': ... })
  • correctly match xxx:abc and not match xxxabc
    • in other words, the generated regex should be /^\/([^:]+):abc\/?$/i and not /^\/([^:]+)abc\/?$/i (added the missing colon)

A route of /:foo([^:]+)\::bar should additionally (on top of above expectations):

  • not have bar contain the separating colon
    • e.g. /abc:def should result in { foo: 'abc', bar: 'def' } and not { 'foo:': 'abc', bar: ':def' }

Actual behavior

Short version:

For example, the following route:

/:entityType([^:]+)\::entityID

When provided a path such as:

/section:aaabbbccc

... will result in the following parameters in $route.params:

{
    'entityType:': 'section',  // note the extra colon in the *key*
    entityID: ':aaabbbccc',  // note the extra colon in the *value*
}

Long version:

Any parameter that's followed immediately by \:<something> (e.g. /:foo([^:]+)\:abc) appears to be mis-parsed. Specifically, the \: appears to be gobbled up and thus ignored in the actual route.

The example /:foo([^:]+)\:abc results in a regexp of /^\/([^:]+)abc\/?$/i โ€” note the dropped colon.

This has the following consequences:

  1. The parameter name of the preceding parameter is appended a : (cases /a/ and /b/ in repro link)
  2. The : in the trailing value is dropped, e.g. /:foo([^:]+)\:abc matches xxxabc but not xxx:abc (case /b/ห™in repro)
  3. If the part immediately following the \: is itself a parameter, that parameter is value is prepended a : (this is a direct consequence of the incorrect regex) (case /a/ in repro)

Note that this only seems to happen with : (or rather \: / '\\:'); symbols such as ! or - appear to work fine (case /c/ in repro).

Additional information

Reproduced locally using [email protected] and online via the playground.

Workaround:

A workaround is to make a "dummy" parameter with (:) as its regex, e.g.:

/:foo([^:]+):_(:)abc

With a path of /xxx:abc, this will correctly match it to the route, and result in the expected $route.params of: { foo: 'xxx', _: ':' }.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghas workaroundA workaround has been found to deal with the issue

    Type

    No type

    Projects

    Status

    ๐Ÿ†• Triaging

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions