Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

incorrect group value for :name* pattern #260

Closed
wanderview opened this issue Aug 26, 2021 · 8 comments · Fixed by #261
Closed

incorrect group value for :name* pattern #260

wanderview opened this issue Aug 26, 2021 · 8 comments · Fixed by #261

Comments

@wanderview
Copy link

If you run:

const { pathToRegexp } = require('path-to-regexp');
pathToRegexp(':name*')

You will get this regexp:

/^([^\/#\?]+?)*[\/#\?]?$/i

This regexp does not produce a proper matched group value, though. From devtools:

var r = /^([^\/#\?]+?)*[\/#\?]?$/
undefined
r.exec('foobar')
(2) ['foobar', 'r', index: 0, input: 'foobar', groups: undefined]

The matched value is "r" instead of "foobar".

I think path-to-regexp should instead make the current grouping in the regexp non-matching and add a matching group around the repeating * modifier. Like this:

/^((?:[^\/#\?]+?)*)[\/#\?]?$/i

This is my plan for fixing this in URLPattern.

@kettanaito
Copy link
Contributor

I'd like to open a pull request to tackle this. Will add the respective tests to catch any regressions.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Aug 26, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Aug 26, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
@kettanaito
Copy link
Contributor

kettanaito commented Aug 27, 2021

It looks like the suggested fix cannot be generally applied. When this expression is changed:

route += `(${token.pattern})${token.modifier}`;

to:

route += `((?:${token.pattern})${token.modifier})`;

It will result in arbitrary characters being caught in the non-matching group:

  • Path: /user(s)?/:userId
  • RegExp: ^\/user((?:s)?)\/([^\\/#\\?]+?)
  • Match:
/^\/user((?:s)?)\/([^\\/#\\?]+?)/.exec('/user/123')
(3) ["/user/1", "", "1", index: 0, input: "/user/123", groups: undefined]

This is due to the (s)? token getting wrapped in the non-matching group, becoming user((?:s)?) instead of user(s)?.

We can apply the suggested fix only in the case token.modifier === '*'. This retains the previous behavior and fixes the issue above.

I think the same can be said about the + modifier: it has the same issue of not matching the entire path parameter and should also be taken into account within this fix.

const { pathToRegexp } = require('path-to-regexp');
const exp = pathToRegexp(':name*')

exp.exec('foobar')
(2) ['foobar', 'r', index: 0, input: 'foobar', groups: undefined]

@kettanaito
Copy link
Contributor

The fix for both :name* and :name+ paths has been provided and respective tests added in #261.

@wanderview
Copy link
Author

I think the fix should also be applied for :name?. Basically if there is a modifier present at all. When there is no modifier present then the old logic is correct. Does that agree with what you are seeing?

I added an end anchor $ to your regexp above and I get:

/^\/user((?:s)?)\/([^\\/#\\?]+?)$/.exec('/user/123')
(3) ['/user/123', '', '123', index: 0, input: '/user/123', groups: undefined]
/^\/user((?:s)?)\/([^\\/#\\?]+?)$/.exec('/users/123')
(3) ['/users/123', 's', '123', index: 0, input: '/users/123', groups: undefined]

@kettanaito
Copy link
Contributor

I’ll add “+” scenario later next week as well.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Aug 31, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
@wanderview
Copy link
Author

I think the fix should also be applied for :name?

You can ignore this feedback from me above. You are indeed correct we don't need the extra non-capturing group for the optional modifier.

chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 1, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 1, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this issue Sep 1, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}
blueboxd pushed a commit to blueboxd/chromium-legacy that referenced this issue Sep 1, 2021
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}
@kettanaito
Copy link
Contributor

The fix implemented in #261 is ready for review.

moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Sep 3, 2021
…e*' patterns., a=testonly

Automatic update from web-platform-tests
URLPattern: Fix matched values for ':name*' patterns.

This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}

--

wpt-commits: 72cebca780a3165482da11103f28b4fb4752aed4
wpt-pr: 30203
spinda pushed a commit to PLSysSec/cachet-firefox that referenced this issue Sep 8, 2021
…e*' patterns., a=testonly

Automatic update from web-platform-tests
URLPattern: Fix matched values for ':name*' patterns.

This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}

--

wpt-commits: 72cebca780a3165482da11103f28b4fb4752aed4
wpt-pr: 30203
warren-bank added a commit to warren-bank/node-serve that referenced this issue Dec 22, 2021
primary use case:
* regex pattern matches a subset of the URL pathname
  example (configs):
    - source:
        '/foo/:bar*'
    - destination:
        '/:bar'
    - purpose:
      * 'rewrites' rule would be used to silently ignore
        the leading 'foo/' directory in path
      * 'redirects' rule would be used to trigger a 301 redirect
        to a new URL that removes
        the leading 'foo/' directory in path
  example (behavior):
    - request URL path:
        '/foo/a/b/c/d/e/f.txt'
    - :bar interpolates to value (before encoding):
        'a/b/c/d/e/f.txt'
    - :bar interpolates to value (after default encoding):
        encodeURIComponent('a/b/c/d/e/f.txt') === 'a%2Fb%2Fc%2Fd%2Fe%2Ff.txt'
* if the corresponding 'rewrites' or 'redirects' rule includes the flag:
    {"raw": true}
  then the raw value will be returned without any encoding

based on:
* upstream PR 85
    vercel/serve-handler#85

references:
* pathToRegExp.compile(data, options)
    https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp

road blocks:
* pathToRegExp bug
    pillarjs/path-to-regexp#260
    pillarjs/path-to-regexp#261
  status:
  - the desired behavior will remain broken until this PR is merged
  - 'source' patterns that match one or more '/' characters
    cause the library to throw an Error for a failed assertion
wanderview added a commit to wanderview/urlpattern-polyfill that referenced this issue Jan 7, 2022
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp:

  pillarjs/path-to-regexp#260

This commit essentially applies the proposed fix in:

  pillarjs/path-to-regexp#261

And adds the WPT tests from:

  https://chromium-review.googlesource.com/c/chromium/src/+/3123654
wanderview added a commit to wanderview/urlpattern-polyfill that referenced this issue Jan 7, 2022
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp:

  pillarjs/path-to-regexp#260

This commit essentially applies the proposed fix in:

  pillarjs/path-to-regexp#261

And adds the WPT tests from:

  https://chromium-review.googlesource.com/c/chromium/src/+/3123654
wanderview added a commit to wanderview/urlpattern-polyfill that referenced this issue Jan 11, 2022
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp:

  pillarjs/path-to-regexp#260

This commit essentially applies the proposed fix in:

  pillarjs/path-to-regexp#261

And adds the WPT tests from:

  https://chromium-review.googlesource.com/c/chromium/src/+/3123654
kenchris pushed a commit to kenchris/urlpattern-polyfill that referenced this issue Jan 11, 2022
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp:

  pillarjs/path-to-regexp#260

This commit essentially applies the proposed fix in:

  pillarjs/path-to-regexp#261

And adds the WPT tests from:

  https://chromium-review.googlesource.com/c/chromium/src/+/3123654
@jeffmcaffer
Copy link

FWIW, I'd love a fix for this as well. Just stumbled on the problem. At least for me it seems to only happen with no leading '/'. So you can work around the problem by prefixing the pattern and target with a '/'. Bit of a hassle but seems to work.
Otherwise, awesome library! Thanks.

mjfroman pushed a commit to mjfroman/moz-libwebrtc-third-party that referenced this issue Oct 14, 2022
This fixes the problem where:

  const p = new URLPattern({ pathname: ':name*' });
  const r = p.exec('foobar');
  console.log(r.pathname.groups.name);

Would log 'r' instead of 'foobar'.

This is an upstream bug in path-to-regexp as well:

pillarjs/path-to-regexp#260

Fixed: 1243773
Change-Id: I402d2b8cba48386d9ae02a493068488a7ad91d70
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3123654
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/main@{#917069}
NOKEYCHECK=True
GitOrigin-RevId: be37e4708c7181c30842d55a7fad9562a36bd1db
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants