阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Nginx rewrite模块探究与实验

156次阅读
没有评论

共计 6037 个字符,预计需要花费 16 分钟才能阅读完成。

关于 nginx 中的 rewrite,之前的理解总感觉有些不精确。比如以下问题,经过 rewrite 之后:

      什么情况会返回 200?

      什么情况会返回 301/302?

      什么情况浏览器里的 url 不变?

      什么情况浏览器里的 url 会变?

      什么情况匹配一次就不再匹配之后的规则或 location?

      什么情况匹配到一条规则后,会以 rewrite 之后的 url 再到 server 段走一遍

如果读者能理解清楚以上问题,则说明对 nginx 的 rewrite 整体上已经有了全面的认识。

接下来我们针对以上问题,来通过试验逐一解答

实验环境:nginx 1.8

网站根目录:nginx/html

注:在 http 段或者 server 段添加 rewrite_log on; 并且设置 error_log 为 notice 级别,可以在 error og 里捕捉到 rewrite 的过程

一、先实验一个最简单的:http://172.16.25.162/ljk.html。该文件不在在 html 下,而在在 html/wordpress 下

server {

        listen        80;

        server_name  localhost;

        rewrite_log on;

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1;

          }

        }

观察 nginx 访问日志和错误日志

access_log:

“GET /ljk.html HTTP/1.1” 200

error_log:

*98 “^/(.+\..+)$” matches “/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

*98 rewritten data: “/wordpress/ljk.html”, args: “”, client:172.16.25.3, server: localhost, request: “GET /ljk.html

浏览器里的 url 没有改变,状态码返回 200

Nginx rewrite 模块探究与实验

由此可见,如此配置实现了一个最简单的内部跳转。

二、再进一步,看一个两级的 rewrite。将 html/wordpress/ 下的 ljk.html 移到 html/ljk/ 下,并且在 location /wordpress 下配置重写规则

        location / {

            root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1;

          }

        }

        location /wordpress  {

            if (!-e $request_filename) {

              rewrite ^/wordpress/(.+\..+)$ /ljk/$1;

            }

        }

access_log:

“GET /ljk.html HTTP/1.1” 200

error_log: 可以看到两次匹配与重写的过程

*99 “^/(.+\..+)$” matches “/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

*99 rewritten data: “/wordpress/ljk.html”, args: “”, client:172.16.25.3, server: localhost, request: “GET /ljk.html

*99 “^/wordpress/(.+\..+)$” matches “/wordpress/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

*99 rewritten data: “/ljk/ljk.html”, args: “”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

浏览器 url 依然不变

Nginx rewrite 模块探究与实验

以上两个实验对用户透明,用户通过返回码或者地址栏 url 均不可感知 rewrite 的存在,可以看做‘内部重定向’;那么什么时候会产生‘外部重定向’呢,现在先试试 Permanent、redirect 两个标志

三、重写规则后加上 permanent 标志

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1 permanent;

          }

        }

访问 http://172.16.25.162/ljk.html

access_log:

GET /ljk.html HTTP/1.1″ 301    返回 301

GET /wordpress/ljk.html HTTP/1.1″ 200

注意此处产生了两个请求

error_log:

*107 “^/(.+\..+)$” matches “/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

      *107 rewritten redirect: “/wordpress/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

浏览器地址栏变成了 rewrite 后的 url

Nginx rewrite 模块探究与实验

四、重写规则后加上 redirect 标志

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1 redirect;

          }

access_log:    两个请求

“GET /ljk.html?sds HTTP/1.1” 302    临时重定向 302

“GET /wordpress/ljk.html HTTP/1.1” 200

error_log:

*108 “^/(.+\..+)$” matches “/ljk.html”, client: 172.16.25.3, server: localhost, request: “GET /ljk.html

      *108 rewritten redirect: “/wordpress/ljk.html?sds”, client: 172.16.25.3, server: localhost, request: “GET /ljk.ht        ml?sds

浏览器地址栏变成了 rewrite 后的 url

Nginx rewrite 模块探究与实验

由三四得出结论:Permanent、redirect 两个标志控制是否将重过程在用户端体现出来(即将重写后的 url 显示在客户端)同时返回 301 or 302。

然后再试试 last 和 break 两个标志(需要两层及以上跳转来测试)

按照网上较为普遍的说法:

假如一个 location 里有多条 rewrite 规则,都是不在该 location 继续往下匹配,但是

last:匹配完该条语句后得到的 url,重新到 server 标签下走一遍

break:到此为止(直接以重写后的 url 在服务器寻找资源)

实验环境:删除 html/wordpress 下的 ljk.html,将 ljk.html 放置在 html/ljk/ljk.html, 然后在 server 标签下配置 location /wordpress 的 rewrite 规则

五、先来看下两次 rewrite 规则不加标志的情况

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1;

          }

        }

        location /wordpress  {

            if (!-e $request_filename) {

              rewrite ^/wordpress/(.+\..+)$ /ljk/$1;

            }

        }

access_log:

GET /ljk.html HTTP/1.1″ 200

error_log:    经历两次匹配和重写

      *111 “^/(.+\..+)$” matches “/ljk.html”,

      *111 rewritten data: “/wordpress/ljk.html”, args: “”,

*111 “^/wordpress/(.+\..+)$” matches “/wordpress/ljk.html”,

*111 rewritten data: “/ljk/ljk.html”, args: “”,

浏览器地址栏 url 不变

六、实验 break 标志

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1 break;

          }

        }

        location /wordpress  {

            if (!-e $request_filename) {

              rewrite ^/wordpress/(.+\..+)$ /ljk/$1;

            }

        }

access_log:

    GET /ljk.html HTTP/1.1″ 404

error_log:

    *112 “^/(.+\..+)$” matches “/ljk.html”,

    *112 rewritten data: “/wordpress/ljk.html”, args: “”,

    *112 open() “/usr/local/nginx/html/wordpress/ljk.html” failed (2: No such file or directory),

加了 break,所以在重写成‘wordpress/ljk.html’就没有再走到 location /wordpress
 

七、实验 last 标志

        location / {

          root  /usr/local/nginx/html;

          index  index.shtml index.php index.html;

          if (!-e $request_filename) {

              rewrite ^/(.+\..+)$ /wordpress/$1 last;

          }

        }

        location /wordpress  {

            if (!-e $request_filename) {

              rewrite ^/wordpress/(.+\..+)$ /ljk/$1;

            }

        }

访问 http://172.16.25.162/ljk.html

access_log:

    GET /ljk.html HTTP/1.1″ 200

error_log:

    *113 “^/(.+\..+)$” matches “/ljk.html”,

    *113 rewritten data: “/wordpress/ljk.html”, args: “”,

    *113 “^/wordpress/(.+\..+)$” matches “/wordpress/ljk.html”,

    *113 rewritten data: “/ljk/ljk.html”, args: “”,
 

由五六七可得出结论:

加 break 标志时,url 一旦找到匹配额规则,就会停止继续匹配并以该 rewrite 后额 url 去服务器请求资源;

加 last 标志或者不加任何标志,其‘过程’和‘结果’一致,会以 rewrite 后的 url 再重新到 server 段下走一遍配置。

并且这两个标志都不会改变浏览器地址栏的 url,且返回码亦为 200 或 404 等(即对用户透明)

八、涉及到域名重定向��实验

    server {

        listen        80;

        server_name  localhost;

        rewrite_log on;

        rewrite ^(.*)$ http://www.baidu.com;

}

若 rewrite 规则后不加标志或者加 redircet 标志,都会返回“GET / HTTP/1.1″ 302”临时重定向

当 rewrite 规则后加 permanent 标志,会返回“GET / HTTP/1.1″ 301”永久重定向
 

希望这篇文章能对理解 nginx 的 rewrite 有一些帮助!

更多 Nginx 负载均衡配置 相关教程见以下内容

Nginx 负载均衡配置说明 http://www.linuxidc.com/Linux/2016-03/129424.htm

Linux 下 Nginx+Tomcat 负载均衡和动静分离配置要点  http://www.linuxidc.com/Linux/2016-01/127255.htm

Docker+Nginx+Tomcat7 配置简单的负载均衡  http://www.linuxidc.com/Linux/2015-12/125907.htm

Nginx 负载均衡(主备)+Keepalived  http://www.linuxidc.com/Linux/2015-12/126865.htm

使用 Nginx 作为负载均衡器 http://www.linuxidc.com/Linux/2015-12/125789.htm

使用 Nginx 简单实现负载均衡  http://www.linuxidc.com/Linux/2016-08/134443.htm

Nginx 负载均衡与高可用的实现 http://www.linuxidc.com/Linux/2016-04/130350.htm

Nginx 的详细介绍:请点这里
Nginx 的下载地址:请点这里

本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-10/136220.htm

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-21发表,共计6037字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中