URL 参数过滤时 Nginx URL 重写如何配

作者:袖梨 2026-08-15

URL参数过滤非重写,而是处理查询字符串;Nginx rewrite默认只匹配路径不包含参数,需用$args配合if或map实现带参重写、参数清理或保留等操作。

URL 参数过滤本身不是重写,而是对查询字符串(即 ? 后面的部分)的处理。Nginx 的 rewrite 指令默认不碰参数——它只匹配路径($uri),不包含问号及之后内容。所以“带参重写”实际是:先判断参数,再改路径或调整参数本身。

用 $args 配合 if 实现参数条件重写

这是最直接的方式,适合简单规则。注意 if 在 location 中慎用,但针对参数判断仍较常见。

  1. 匹配并跳转,同时清空参数:比如含 utm_source=ad 的请求统一跳到首页且不带参数

    if ($args ~ utm_source=ad) {

    rewrite ^/.*$ /? permanent;

    }

  2. 保留部分参数、丢弃其余:只留 idlang,其他全去掉

    if ($args ~* "id=([^&]+)&.*lang=([^&]+)") {

    set $new_args "id=$1&lang=$2";

    rewrite ^(.*)$ $1?$new_args? last;

    }

    (末尾两个 ?:第一个表示拼接新参数,第二个表示不继承原参数)

用 map 提前提取参数值,更安全可靠

推荐用于中等以上复杂度场景。map 在 server 级定义,无执行顺序依赖,避免 if 的已知限制。

  1. server 块外(通常放在 http 块)定义映射:

    map $args $target_path {

    default "";

    ~*id=(d+) "/article/$1";

    ~*cat=([a-z]+) "/category/$1";

    }

  2. 在 location 中使用:

    location / {

    if ($target_path) {

    rewrite ^ $target_path? last;

    }

    }

    注意结尾的 ? 表示清除原始参数,只保留重写后路径自带的(如有)

单纯过滤或屏蔽特定参数(不重写路径)

有时只需删掉某个参数(如 tracking 类),不改变路径。

  1. set 清空 $args 再重建:

    if ($args ~ "ref=[^&]*") {

    set $args $args;

    rewrite ^(.*)$ $1? break;

    }

    这不行——$args 是只读别名?不对,$args 可写,但正则替换需更精细

  2. 正确做法:用 map 构造干净参数串,或搭配 perl_set(需编译支持)。更实用的是用 try_files + 内部重定向规避参数传递,或交由后端处理

常见陷阱与关键细节

绕不开的几个点,配错就失效:

  1. 问号永远不在 $uri 里:location /search 不会匹配 /search?q=nginx,因为 $uri/search$args 才是 q=nginx
  2. rewrite 结尾加 ? = 丢参数:rewrite /old /new? last → 到 /new 且无任何 query;不加 ? 就会把原参数自动带上
  3. ~ 区分大小写,~* 不区分:匹配 ID=123 要用 ~* id=,否则漏掉
  4. 不要在 if 里嵌套多个 rewrite:Nginx 不支持,会报错;要用 map 或拆成不同 location 处理

相关文章

精彩推荐