Nginx Rewrite

697 阅读3分钟

总结

  • redirect:返回302临时重定向,浏览器地址栏会显示跳转后的URL地址,爬虫不会更新URL。
  • permanent:返回301永久重定向,浏览器地址栏会显示跳转后的URL地址,爬虫会更新URL。
  • break:停止处理后续rewrite指令集,不会跳出location作用域,不再进行重新查找,终止匹配,URL地址不变。
  • last:停止处理后续rewrite指令集,跳出location作用域,并开始搜索与更改后的URI相匹配的location,URL地址不变。

访问关系

   客户端             Nginx             OpenResty
192.168.1.136  --> 192.168.1.134 --> 192.168.1.132

Nginx配置

events {
  worker_connections 1024;
}
http {
    log_format  haha  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '$http_user_agent "x_forwarded_for":$http_x_forwarded_for'  '$server_name $upstream_addr $upstream_status $request_time  $upstream_response_time';
    access_log /var/log/nginx/haha.log haha;
    rewrite_log on;  #开启记录rewrite日志
    error_log  /var/log/nginx/rewrite.log notice;
  server {
    listen 80;
    location / {
      #当请求中cookie中包含CRIS
      if ($http_cookie ~* "(CRIS)") {
         echo "result is:$1";  #这里的$1指的是if里匹配到的(CRIS)
          #注意这里不要写成/rr/$1,否则重定向的地址会是/rr//CRIS,就无法匹配到/rr/CRIS这个location,因此会再次匹配/这个location,重复50次后返回500 Error。
         rewrite ^(.*)$ /rr$1;   #这里的$1指的是uri的内容
    
      }
      # [^;]+ 表示1个以上不是;的字符串 
      #  ;|$ 表示;或者空格行(linux空格行以$开头)
     if ($http_cookie ~* "a=([^;]+)(;|$)") {            echo "http_cookie is:$http_cookie";
         echo "id is:$1";
         echo "other is:$2";
     }
    }
    location  /rr/CRIS {
        echo "welcome CIRS";
    }
  }
}

验证

首先匹配到第二个if:$http_cookie ~* "a=([^;]+)(;|$)"

❯ curl 192.168.1.132/CRIS  --cookie "a=test;"
http_cookie is:a=test;
id is:test
other is:;

查看rewrite的日志: 先匹配第一个if没命中,然后找第2个if成功命中。

2020/08/29 12:49:08 [notice] 12610#12610: *432 "(CRIS)" does not match "a=test;", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:49:08 [notice] 12610#12610: *432 "a=([^;]+)(;|$)" matches "a=test;", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"

发送请求匹配第一个if

❯ curl 192.168.1.132/CRIS  --cookie "a=CRIS"  -L -i
HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Sat, 29 Aug 2020 11:57:49 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

welcome CIRS

查看rewrite日志 但是这里发现在首先命中了第1个if后,还会接着去匹配第二个if,这里的第2个if也匹配到了,第2个if的内容也会执行,只是因为我们做了rewrite,所以控制台上没有看到第2个if内的输出结果。

2020/08/29 12:51:36 [notice] 12610#12610: *433 "(CRIS)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:51:36 [notice] 12610#12610: *433 "^(.*)$" matches "/CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:51:36 [notice] 12610#12610: *433 rewritten data: "/rr/CRIS", args: "", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:51:36 [notice] 12610#12610: *433 "a=([^;]+)(;|$)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"

假如修改rewrite ^(.*)$ /rr$1 last;后面加上last参数,直接跳出该locaiton,第2个if的动作就不会执行了。

❯ curl 192.168.1.132/CRIS  --cookie "a=CRIS"  -L -i
HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Sat, 29 Aug 2020 11:57:49 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

welcome CIRS
2020/08/29 12:54:39 [notice] 12805#12805: *440 "(CRIS)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:54:39 [notice] 12805#12805: *440 "^(.*)$" matches "/CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:54:39 [notice] 12805#12805: *440 rewritten data: "/rr/CRIS", args: "", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"

假如修改rewrite ^(.*)$ /rr$1 break;后面加上break参数,这次请求就在这个location里终结,会接着执行第2个if里的内容。

❯ curl 192.168.1.132/CRIS  --cookie "a=CRIS"
result is:/CRIS
2020/08/29 12:56:48 [notice] 12828#12828: *441 "(CRIS)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:56:48 [notice] 12828#12828: *441 "^(.*)$" matches "/CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:56:48 [notice] 12828#12828: *441 rewritten data: "/rr/CRIS", args: "", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"

假如修改rewrite ^(.*)$ /rr$1 redirect;后面加上redirect参数,nginx会向客户端返回302临时重定向。并且第二个if也不会执行。改成permanent结果类似,nginx向客户端返回301永久重定向。

❯ curl 192.168.1.132/CRIS  --cookie "a=CRIS"  -L -i
HTTP/1.1 302 Moved Temporarily
Server: openresty/1.15.8.2
Date: Sat, 29 Aug 2020 04:59:26 GMT
Content-Type: text/html
Content-Length: 151
Location: http://192.168.1.132/rr/CRIS
Connection: keep-alive

HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Sat, 29 Aug 2020 04:59:26 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

welcome CIRS

2020/08/29 12:59:26 [notice] 12852#12852: *447 "(CRIS)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:59:26 [notice] 12852#12852: *447 "^(.*)$" matches "/CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 12:59:26 [notice] 12852#12852: *447 rewritten redirect: "/rr/CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"

假如不加rewrite这条语句,会依次匹配第1个if和第2个if,两个if都会执行,最终在控制台上看到的输出是第2个if的输出。

❯ curl 192.168.1.132/CRIS  --cookie "a=CRIS"  -L -i
HTTP/1.1 200 OK
Server: openresty/1.15.8.2
Date: Sat, 29 Aug 2020 05:02:04 GMT
Content-Type: text/plain
Transfer-Encoding: chunked
Connection: keep-alive

http_cookie is:a=CRIS
id is:CRIS
other is:
2020/08/29 13:02:04 [notice] 12931#12931: *449 "(CRIS)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"
2020/08/29 13:02:04 [notice] 12931#12931: *449 "a=([^;]+)(;|$)" matches "a=CRIS", client: 192.168.1.136, server: , request: "GET /CRIS HTTP/1.1", host: "192.168.1.132"