以任意顺序匹配某些 url 参数的正则表达式

Regex that matches certain url parameters in arbitrary order

我正在尝试在 NGINX 中设置缓存并且只需要包含某些参数(如果给定的话)来创建密钥并缓存站点。但是,如果参数的顺序不同,或者根本没有给定参数,我就无法使用它。

网址可以是:

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

只有路径和param1(可选)和param2(可选)与缓存相关。应忽略其他参数。所以最后我需要三个命名的捕获组,我可以为 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";

但显然我的正则表达式不起作用https://regex101.com/r/Hf2jCj/1

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

使用 map,您可以根据需要添加任意数量的正则表达式。正则表达式按顺序处理,直到找到匹配项。有关详细信息,请参阅 this document

在较不具体的模式之前列出较具体的模式。

您可能希望匹配包含 param1+param3param3+param1before 的 URL ] 模式来匹配只有一个参数的 URL,before 匹配没有任何参数的 URL。

例如:

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;
}