使用 nginx 进行带条件的反代文件屏蔽

 

在运营服务器时,通常会有这样的需求:对一些路径,对于某些符合条件的用户(如 UA、IP)等返回一类页面,其余用户正常提供服务。最近研究了一下 nginx 的做法。 通常,只要在 location 中使用 if 指令就能给解决很多问题,但是如果某个路径使用了 proxy_pass 反代,那么就不能出现在 if 中,需要特殊的处理。

首先通过某种方式匹配需要特殊处理的用户,比如:

map $http_user_agent $is_special {
  default 0;
  "~*Mozilla/5\.0 \(Windows NT 6\.1; WOW64\)" 1;
  "~*Chrome/41\.0" 1;
}

然后通过 nginx 的 rewrite 功能,将需要分别处理的路径重写到某个内部路径上:

if ($request_uri ~ /help|^/assets/.*\.js\.map$|\.git|robots\.txt$) {
    rewrite ^(.*)$ /@specially-process/$request_uri;
}

最后在此内部路径上判断条件分别处理即可。首先用 internal 标记为内部 path 防止用户命中。其次判断如果是特殊用户,则直接返回 404;否则,rewrite 回原来的路径上,由正常的 location 进行处理。

location /@specially-process {
    internal;
    if ($is_special) {
        return 404;
    }
    rewrite ^(.*)$ $request_uri;
}

当然,也可以直接在 /@sepcially-process 中处理一般情况,这时候需要在 rewrite 命令后添加 break,表示停止进一步匹配,就在原地处理。

注意:如果在 location 里面中配置 rewrite,需要小心产生 rewrite 环。