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

how to get named keys with a negative look ahead? #252

Open
daniellizik opened this issue Apr 21, 2021 · 11 comments
Open

how to get named keys with a negative look ahead? #252

daniellizik opened this issue Apr 21, 2021 · 11 comments

Comments

@daniellizik
Copy link

say i have a request with a url

/foo/123

how can I match anything except "foo" while having the first parameter be a named key?

// in js
/(?!foo).+/[0-9]+
// also need the first param, but this is invalid
/(?!foo):animal/:num
/dog/123       => match { animal: 'dog', num: 123 }
/cat/7893434   => match { animal: 'cat', num: 7893434 }
/foo/123       => no match { animal: null }
@DavidHenri008
Copy link

DavidHenri008 commented Aug 3, 2021

Unfortunately, I was never able to make it works as you want. I also have a situation where this would be needed.

@DavidHenri008
Copy link

After some investigation, I found out that this seems to work:
/:animal((?!foo)[a-zA-Z0-9]+)/:id([0-9]+)
See CodeSandbox

@jonchurch
Copy link
Member

@DavidHenri008 has the right idea. This falls under "Custom Matching Parameters" in the docs.

Essentially, you can put a regex in parenthesis after a named parameter in order to define a custom regex.

@jonchurch
Copy link
Member

jonchurch commented Aug 6, 2021

Actually I'll reopen this, I realize now the real issue was you couldn't start a regex with ?. I think this isn't a bug, and luckily it gives a specific error message. Perhaps that error message should be updated to say that you need to enclose a lookahead/behind group in it's own parens? I think that is the real issue here, misunderstanding that these capture groups still need to be enclosed, as I believe they do with JS regex anyways.

The logic was I believe added in #207 and the code itself throwing is https://github.com/pillarjs/path-to-regexp/blob/master/src/index.ts#L85

@jonchurch jonchurch reopened this Aug 6, 2021
@blakeembrey
Copy link
Member

@jonchurch thoughts on what should be changed if this is an open issue? From the implementation POV it’s not a valid regex to start with the ? directly after an opening parenthesis. Need to consider that the parenthesis is an implementation detail of path-to-regexp syntax and not an actual part of the regex.

@jonchurch
Copy link
Member

jonchurch commented Aug 9, 2021

@blakeembrey The best way to prevent someone running into this mistake is likely adding an example to the docs. Thinking about it, a change to the error message is overkill here.

Specifically, adding an example for lookahead/behinds.

@jonchurch jonchurch added the docs label Aug 9, 2021
@aseem-upadhyay
Copy link

aseem-upadhyay commented Feb 28, 2022

Hey @blakeembrey @jonchurch . What's the resolution here. I ran into a similar use case to negate out urls based on a specific keyword occurrence.

something like /:page(!test) meaning this url should be dropped if test occurs

@nvmnghia
Copy link

Bump this. I'm trying to write a regex that excludes a path starting with .well-known.

@luwes
Copy link

luwes commented May 18, 2023

I ran into this (bug?) today with this vercel.json. Any idea what the fix is here?

"source": "/examples/:path((?!vanilla/).*)", "destination": "/examples/vanilla/:path*"

/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/path-to-regexp/index.js:346
  return new RegExp('^' + route, flags(options))
         ^

SyntaxError: Invalid regular expression: /^\/examples\/([^\/]+?)\((?\!vanilla\/)\.(.*)\)(?:\/)?$/: Invalid group
    at new RegExp (<anonymous>)
    at tokensToRegExp (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/path-to-regexp/index.js:346:10)
    at stringToRegexp (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/path-to-regexp/index.js:288:10)
    at pathToRegexp (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/path-to-regexp/index.js:370:10)
    at sourceMatches (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/serve-handler/src/index.js:47:22)
    at toTarget (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/serve-handler/src/index.js:70:18)
    at shouldRedirect (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/serve-handler/src/index.js:174:18)
    at module.exports (/Users/wes/.npm/_npx/aab42732f01924e5/node_modules/serve-handler/src/index.js:583:19)
    at run (file:///Users/wes/.npm/_npx/aab42732f01924e5/node_modules/serve/build/main.js:177:13)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Node.js v18.12.1

@royeden
Copy link

royeden commented Dec 26, 2023

I think I've probably ran into the same issue while trying to use negative lookaheads combined with path params, the way vercel recommends doing this in the nextjs docs:

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
}

My issue is trying the example with path params and expecting it to work:

'/((?!foo/:bar))'

turns into

/^(?:\/((?!foo\/:bar)))[\/#\?]?$/i

instead of the expected

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

@blakeembrey
Copy link
Member

@royeden You can’t put named keys inside the regex, regardless of it being a negative lookahead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants