在 nginx $args 中使用正则表达式捕获组

Win*_*ute 2 regex nginx

作为一些背景,我正在尝试修复带有重复参数的请求,例如:

/products/compare/?ids=554?ids=554
/products/compare/?ids=595,662,726?ids=595,662,726
Run Code Online (Sandbox Code Playgroud)

我的修复 - 有效 - 看起来像这样:

location /products/compare/ {
    if ( $args ~ "(ids=[\d,]+)\?ids=[\d,]+" ) {
        set $id $1;
        rewrite ^.*$ $scheme://$host/$uri$is_args$id? permanent;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是关于set $id $1;以及为什么有必要

我直接在重写中使用 capture-group变量$1

rewrite ^.*$ $scheme://$host/$uri$is_args$1? permanent;
Run Code Online (Sandbox Code Playgroud)

但该变量并未被填充。

为什么不?

Ric*_*ith 6

rewrite指令的第一个参数是一个正则表达式,其中可能包含编号的捕获。因此,当rewrite输入语句时,所有编号的捕获都会重置。

作为使用set指令的替代方法,您可以在语句的正则表达式中使用命名捕获if

例如:

if ( $args ~ "(?<id>ids=[\d,]+)\?ids=[\d,]+" ) {
    rewrite ^ $scheme://$host/$uri$is_args$id? permanent;
}
Run Code Online (Sandbox Code Playgroud)

当然,您实际上并不需要使用rewrite. 如果您return改为使用,则数字捕获仍保留在范围内。

例如:

if ( $args ~ "(ids=[\d,]+)\?ids=[\d,]+" ) {
    return 301 $scheme://$host/$uri$is_args$id;
}
Run Code Online (Sandbox Code Playgroud)