关于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 { listen80; server_namelocalhost; 【运维|nginx rewrite模块探究与实验】rewrite_log on; location / { root/usr/local/nginx/html; indexindex.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 ![]() 文章图片 由此可见,如此配置实现了一个最简单的内部跳转。 |
location / { root/usr/local/nginx/html; indexindex.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依然不变 ![]() 文章图片 |
三、重写规则后加上 permanent 标志
location / { root/usr/local/nginx/html; indexindex.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 ![]() 文章图片 |
location / { root/usr/local/nginx/html; indexindex.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.html?sds 浏览器地址栏变成了rewrite后的url ![]() 文章图片 |
然后再试试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; indexindex.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不变 |
location / { root/usr/local/nginx/html; indexindex.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 |
location / { root/usr/local/nginx/html; indexindex.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 { listen80; server_namelocalhost; rewrite_log on; rewrite ^(.*)$ http://www.baidu.com; } 若rewrite规则后不加标志或者加redircet标志,都会返回“GET / HTTP/1.1" 302”临时重定向 当rewrite规则后加permanent 标志,会返回“GET / HTTP/1.1" 301”永久重定向 |
推荐阅读
- 云原生微服务技术趋势解读
- 韵达基于云原生的业务中台建设 | 实战派
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 运维|如何限制IP 通过 SSH连接服务器
- 运维|Linux 禁止用户或 IP通过 SSH 登录
- linux|apt update和apt upgrade命令 - 有什么区别()
- 服务器|用旧手机搭建服务器并实现内网穿透不需要root(本人亲测很多次最简单的一个)
- GitHub|7 款可替代 top 命令的工具
- Linux系统网络编程|Linux系统(权限管理)
- 企业实战|Linux 五种IO模型详细图解