Web架构之Nginx重定向Rewrite

1、Rewrite 简介

和Apache等Web服务软件一样,Nginx Rewrite的主要功能是实现URL的地址重写,以及重定向Nginx的Rewrite规则需要PCRE软件的支持,通过Perl兼容正则表达式语法进行规则的匹配

Rewrite使用场景:
1.URL访问跳转:支持开发设计,页面跳转,兼容性支持,展示效果
2.SER优化:依赖于url路径,以便支持搜索引擎录入
3.维护:后台维护,流量转发等
4.安全:伪静态,真是动态页面进行伪装

Rewrite 语法

Syntax:rewrite regex replacement {flag};
default:none
Context:server、location、if

// 所有的请求转发至/pages/maintain.html
rewrite ^(.*)$ /pages/maintain.html break;

正则表达式:

表达式 说明
. 匹配除换行符以外的任意字符
? 重复0次或1次
+ 重复1次或更多次
* 匹配所有
\d 匹配数字
^ 匹配字符串的开始
$ 匹配字符串的结尾
重复n次
重复n次或更多次
[c] 匹配单个字符c
[a-z] 匹配a-z小写字母的任意一个

正则表达式中特殊字符

// \ 转义字符
rewrite index\.php$ /pages/maintain.html break;

// ()用于匹配括号之间的内容, 通过$1,$2调用 
if ($http_user_agent ~ Chrome){
      rewrite ^(.*)$ /chrome/$1 break;
  }

正则表达式终端测试工具

$ yum install -y pcre-tools
$ pcretest
PCRE version 8.32 2012-11-30

re> /(\d+)\.(\d+)\.(\d+)\.(\d+)/
data> 10.0.0.7
 0: 10.0.0.7
 1: 10
 2: 0
 3: 0
 4: 7

Rewrite标记Flag:

flag 说明
last 停止rewrite检测
break 停止rewrite检测
redirect 返回302临时重定向,地址栏会显示跳转后的地址
permanent 返回301永久重定向,地址栏会显示跳转后的地址

对比flag中break和last:

$ vim /etc/nginx/conf.d/rewrite.conf 
server {
    listen 80; 
    server_name localhost; 
    root /soft/code; 
       
    location ~ ^/break {
          rewrite ^/break /test break; 
        }
          
    location ~ ^/last {
          rewrite ^/last /test last;
        }

    location /test {
          default_type application/json; 
				  return 200 '{"status":"success"}';
        } 
}

测试break

$ curl 127.0.0.1/break/xx.html
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.16.1</center>
</body>
</html>

测试last

$ curl 127.0.0.1/last
{"status":"success"}

last 与 break 对比总结:
1.last:会新建立一个请求, 所以会重新进行匹配
2.break:跳出rewrite阶段,不会在匹配。

对比flag中redirect和permanent:

[root@lb01 /]# cat /application/nginx/conf/extra/rewrite.conf 
server {
      listen 80;
      server_name localhost;
      root /soft/code;
      location ~ ^/jason {
          rewrite ^/jason http://www.baidu.com redirect; # 临时重定向
        # rewrite ^/jason http:// www.baidu.com permanent; # 永久重定向
                }
}

2、Rewrite 应用场景

可以调整用户浏览的URL
为了让搜索引擎收录网站内容及用户体验更好
网站换新域名后,让旧的域名的访问跳转到新的域名上

2.1、基于uri做rewrite

正常访问: 127.0.0.1/course-11-22-33.html
改写后: 127.0.0.1/course/11/22/course_33.html

1.环境准备

$ mkdir /soft/code/course/11/22/ -p
$ echo "<h1>Nginx</h1>"  > /soft/code/course/11/22/course_33.html

2.修改nginx配置文件

$ vim  /etc/nginx/conf.d/rewrite.conf
server {
     listen 80;
     root /soft/code;
     index index.html;

     location / {
         rewrite_log on;
         error_log /var/log/nginx/rewrite.log notice;
         rewrite ^/course-(\d+)-(\d+)-(\d+).html /course/$1/$2/course_$3.html break;
        }
}

3.测试结果

$ curl  127.0.0.1/course-11-22-33.html
<h1>Nginx</h1>

// 截一段rewrite日志
2020/03/14 14:21:24 [notice] 2432#2432: *53 rewritten data: "/course/11/22/course_33.html", args: "", client: 127.0.0.1, server: , request: "GET /course-11-22-33.html HTTP/1.1", host: "127.0.0.1"

2.2、基于http请求头做rewrite

可以根据http请求头的变量来匹配做rewrite

if ($http_user_agent ~* "Chrome") {
       rewrite ^/nginx http://www.baidu.com/index.html redirect;
                }

别名和Rewrite的区别:
1)用别名效率高,但是看不到改过的域名
2)用Rewrite 301跳转的话,能看到新的域名,但是需要再次发送HTTP请求

3、Rewrite 案例

3.1、案例一

输入:127.0.0.1/jason-2018-11-15_book/index.html
跳转:127.0.0.1/jason/2018/11/15_book/index.html

1.环境准备

$ mkdir /soft/code/jason/2018/11/15_book/ -p
$ echo "book" > /soft/code/jason/2018/11/15_book/index.html

2.修改nginx配置文件

$ cat /etc/nginx/conf.d/rewrite.conf
server {
     listen 80;
     root /soft/code;
     index index.html;

     location / {
        index index.html;
        rewrite_log on;
        error_log /var/log/nginx/rewrite.log notice;
        rewrite ^/jason-(\d+)-(\d+)-(\d+)_book/index.html /jason/$1/$2/$3_book/index.html break;
    }
}

3.测试结果

$ curl 127.0.0.1/jason-2018-11-15_book/index.html
book

// 截一段rewrite日志
2020/03/14 14:29:01 [notice] 3371#3371: *58 "^/jason-(\d+)-(\d+)-(\d+)_book/index.html" matches "/jason-2018-11-15_book/index.html", client: 127.0.0.1, server: , request: "GET /jason-2018-11-15_book/index.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:29:01 [notice] 3371#3371: *58 rewritten data: "/jason/2018/11/15_book/index.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-11-15_book/index.html HTTP/1.1", host: "127.0.0.1"

3.2、案例二

输入:127.0.0.1/jason-2018-12-29_word/xxx.html
跳转:127.0.0.1/jason/2018/12/29_word/xxx.html

1.环境准备

$ mkdir /soft/code/jason/2018/12/29_word/ -p
$ echo "word1" > /soft/code/jason/2018/12/29_word/1.html
$ echo "word2" > /soft/code/jason/2018/12/29_word/2.html
$ echo "word3" > /soft/code/jason/2018/12/29_word/3.html

2.修改nginx配置文件

$ cat /etc/nginx/conf.d/rewrite.conf
server {
     listen 80;
     root /soft/code;
     index index.html;

     location / {
        index index.html;
        rewrite_log on;
        error_log /var/log/nginx/rewrite.log notice;
        rewrite ^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$  /jason/$1/$2/$3_word/$4 break;
    }
}

3.测试结果

$ curl 127.0.0.1/jason-2018-12-29_word/1.html
word1
$ curl 127.0.0.1/jason-2018-12-29_word/2.html
word2
$ curl 127.0.0.1/jason-2018-12-29_word/3.html
word3

// 截一段rewrite日志
2020/03/14 14:32:14 [notice] 3385#3385: *65 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/1.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/1.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:14 [notice] 3385#3385: *65 rewritten data: "/jason/2018/12/29_word/1.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/1.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:15 [notice] 3385#3385: *66 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/2.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/2.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:15 [notice] 3385#3385: *66 rewritten data: "/jason/2018/12/29_word/2.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/2.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:16 [notice] 3385#3385: *67 "^/jason-(\d+)-(\d+)-(\d+)_word/(.*)$" matches "/jason-2018-12-29_word/3.html", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/3.html HTTP/1.1", host: "127.0.0.1"
2020/03/14 14:32:16 [notice] 3385#3385: *67 rewritten data: "/jason/2018/12/29_word/3.html", args: "", client: 127.0.0.1, server: , request: "GET /jason-2018-12-29_word/3.html HTTP/1.1", host: "127.0.0.1"

4、Rewrite额外补充

Rewrite 匹配优先级:
1.执行server块的rewrite指令
2.执行location匹配
3.执行选定的location中的rewrite

Rewrite 优雅书写:

server { 
	listen 80; 
	server_name www.bgx.com bgx.com; 
	if ($http_host = nginx.org){ 
	rewrite (.*) http://www.bgx.com$1; 
		} 
}

# 改良版 
server {
	listen 80;
	server_name bgx.com;
	rewrite ^ http://www.bgx.com$request_uri?; 
}

	server { 
	listen 80;
	 server_name www.bgx.com; 
}
posted @ 2020-03-14 14:35  jasonminghao  阅读(662)  评论(0编辑  收藏  举报