共计 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
由此可见,如此配置实现了一个最简单的内部跳转。
二、再进一步,看一个两级的 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 依然不变
以上两个实验对用户透明,用户通过返回码或者地址栏 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
四、重写规则后加上 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
由三四得出结论: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