Home > other >  Regex that matches certain url parameters in arbitrary order
Regex that matches certain url parameters in arbitrary order

Time:04-12

Im trying to setup caching in NGINX and need to include just certain parameters (if given) to create a key and cache the site. But I don't get it to work if the parameters are in a different order or, as it is also possible, not given at all.

The URLs can be:

https://www.example.com/xyz/
https://www.example.com/xyz/?param1=123&param2=456&param3=789
https://www.example.com/xyz/?param2=456&param3=789&param1=123
https://www.example.com/xyz/?param3=789&param1=123&param2=456
https://www.example.com/xyz/?param1=123&param3=789&param2=456
https://www.example.com/xyz/?param1=123&param2=456

Only the path and param1 (optional) and param2 (optional) are relevant for caching. Other parameters should be ignored. So in the end I need three named capture groups that I can create a mapping for NGINX:

map $request_uri $request_uri_path {
  "~^(?P<path>[^?]*)(?:\?.*)?(?P<p1>param1\=[^&]*) (?:\&.*)?(?P<p2>param3\=[^&]*) $"  $path$p1$p2;
}
fastcgi_cache_key "$scheme$request_method$host$request_uri_path";

But obviously my regex is not working https://regex101.com/r/Hf2jCj/1

~^(?P<path>[^?]*)(?:\?.*)?(?P<p1>param1\=[^&]*) (?:\&.*)?(?P<p2>param3\=[^&]*) $

CodePudding user response:

With a map you can add as many regular expressions as you need. The regular expressions are processed sequentially until a match is found. See this document for details.

List the more specific patterns before the less specific patterns.

You might want to match URLs containing param1 param3 and param3 param1, before patterns to match URLs with just one of the params, before matching the URLs with neither param.

For example:

map $request_uri $request_uri_path {
    ~^(?<path>[^?]*)\?([^&]*&)*(?<p1>param1\=[^&]*)([^&]*&)*(?<p2>param3\=[^&]*) $path$p1$p2;
    ~^(?<path>[^?]*)\?([^&]*&)*(?<p2>param3\=[^&]*)([^&]*&)*(?<p1>param1\=[^&]*) $path$p1$p2;
    ~^(?<path>[^?]*)\?([^&]*&)*(?<p1>param1\=[^&]*)                              $path$p1;
    ~^(?<path>[^?]*)\?([^&]*&)*(?<p2>param3\=[^&]*)                              $path$p2;
    ~^(?<path>[^?]*)                                                             $path;
}
  • Related