urlpattern icon indicating copy to clipboard operation
urlpattern copied to clipboard

URLPattern search param order matters

Open reggi opened this issue 1 year ago • 2 comments

Currently search query parameters are fixed and matches will only occur if they are in the URL in the same order.

new URLPattern({ search: "alpha=true&beta=true" }).exec("https://example.com/hello?alpha=true&beta=true")
{
  inputs: [ "https://example.com/hello?alpha=true&beta=true" ],
  protocol: { input: "https", groups: { "0": "https" } },
  username: { input: "", groups: { "0": "" } },
  password: { input: "", groups: { "0": "" } },
  hostname: { input: "example.com", groups: { "0": "example.com" } },
  port: { input: "", groups: { "0": "" } },
  pathname: { input: "/hello", groups: { "0": "/hello" } },
  search: { input: "alpha=true&beta=true", groups: {} },
  hash: { input: "", groups: { "0": "" } }
}

new URLPattern({ search: "alpha=true&beta=true" }).exec("https://example.com/hello?beta=true&alpha=true")
null

Realizing this I sought out to create a regex pattern that would help solve this:

This regex will require alpha and beta but will also match extra query parameters.

const searchRegExp = (search: string) => `^${search.split('&').map(v => `(?=.*${v})`).join('')}.*$`
searchRegExp('alpha=true&beta=true')
^(?=.*alpha=true)(?=.*beta=true).*$

Here's the match working:

'alpha=true&beta=true'.match(/^(?=.*alpha=true)(?=.*beta=true).*$/)
[ "alpha=true&beta=true" ]
'beta=true&alpha=true'.match(/^(?=.*alpha=true)(?=.*beta=true).*$/)
[ "beta=true&alpha=true" ]

However because there's a positive lookahead in the pattern I think the error is requesting it must not start with ? because this code takes into account the ? in the beginning of any search params string. It would seem that you can't use a ? in the regex because of this collision.

> new URLPattern({ search: "/^(?=.*alpha=true)(?=.*beta=true).*$/" }).exec("https://example.com/hello?alpha=true&beta=true")
Uncaught TypeError: tokenizer error: invalid regex: must not start with ?, and may only contain ascii (at char 2)
    at new URLPattern (ext:deno_url/01_urlpattern.js:70:28)
    at <anonymous>:2:1

I just thought I'd document this behavior for others. Feel free to merge / close this ticket.

reggi avatar May 01 '23 00:05 reggi