0

我正在尝试将 nginx 301 重定向 wordpress 样式foo.com/?p=123样式链接到固定 URL。

If is evil和其他文档中,我收集到危险if的语句是基于参数重定向的唯一方法,我发现这样的配置似乎可以完成工作:

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
}

location = / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    if ($arg_p = 4)  { return 301 /2012/12/hello-world; }
    if ($arg_p = 15) { return 301 /about;               }
    # ... a few hundred more lines like this
}

但是,我猜想通过这种配置,nginx 将不得不通过所有这些if语句来解决顶级foo.com/请求,这可能并不理想。

对这样的大量重定向进行硬编码,同时最大限度地减少语句的危险/成本的“正确”方法是if什么?

4

1 回答 1

1

第一个好主意是将重定向规则放在单独的文件中。这将使主要配置更具可读性。然后可以将具有规则的文件包含在include指令中。

另一个好主意是使用map而不是if,因为它具有更简洁的语法来定义长列表。

假设您决定将规则放入/path/to/redirect/rules.conf. 该文件的内容将如下所示:

# Each map defines the set of rules for one set of conditions.
# The blocks must be sorted in order of priority: every next
# map block has a higher priority than the previous one.
map $arg_p $p_condition {
    default "";

    4              /2012/12/hello-world;
    15             /about;

    # You can use regular expressions
    ~^1[6-9]$      /some/page;
}

# By combining the condition variables you can implement
# some sort of and/or/not logic in your rules
map "${arg_p}#${arg_q}" $pq_condition {

    # Note that it is necessary to inherit the result
    # of the previous map block to preserve them. And this
    # is where the priority of the blocks comes from
    default $p_condition;

    # The values of p _and_ q are 4 and 15
    4#15           /2012/12/hello-world;

    # The value of p is 5 _or_ the value of q is 16
    ~"^5#.*"       /another/page;
    ~"^.*?#16"     /another/page;

    # The value of p is _not_ 8 _and_ the value of q is 30
    ~"^[^8]#30"    /the/very/special/page;
}

# The final block is of the highest priority. It defines
# the variable, which value will be used as the URL for redirection
map $args $url_to_redirect_to {

    # Don't forget this important line
    default $pq_condition;

    # Here's another type of condition: check if the t variable
    # is present in the list of GET paramters
    ~^(&|\?)t=.*$  /yet/another/page;
}

现在剩下要做的就是使用主配置中定义的规则:

# Note that map directives must be placed out of the `server` block
include /path/to/redirect/rules.conf;

server {
    ...

    location = / {
        ...

        if ($url_to_redirect_to != "") {
            rewrite ^ $url_to_redirect_to? permanent;
        }

        ...
    }

    ...
}

乍一看,map块的级联可能看起来有些混乱,但是当您在其中放置大量规则时,您会看到这种方法的优势。

于 2016-01-05T09:00:39.093 回答