Nginx之rewrite功能
1. 什么是nginx rewrite?
Nginx rewrite的主要功能是实现URL地址重写。
Nginx rewrite规则需要PCRE软件的支持。
Nginx服务器使用ngx_http_rewrite_module模块解析和处理Rewrite功能的相关配置。
默认会自带ngx_http_rewrite_module模块,所以不需要单独编译安装。
2. 关于地址重写与地址转发的概念
地址重写
是为了实现地址标准化。
当我们访问google.com与www.goolge.com都会响应www.google.com的页面。
从客户端的角度来看,是两个地址,实际上,只是www.google.com在做响应。
在访问google.com的过程,地址已经重写到了www.google.com上,然后www.google.com给客户端响应。
地址转发
将一个域名指到另一个域名的过程。
区别:

3. Nginx rewirte语法
1. if语法格式
if (condition) {.........}
if使用在server或location块中。
conditon可以是下面这几种情况。
1. 如果条件是变量名;值为空或者0时,if认为条件为false,其他值都为true。
if ($slow) {
......执行语句
}
2. 判断变量是否与字符串相等或者不等。
if ($request_method = POST) {
return 403;
}
= 或者 !=
注意:字符串不需要使用引号。
location / {
root html;
index index.html index.htm;
if ($remote_addr = 192.168.0.105){
return 403;
}
}
当客户端的IP地址为192.168.0.105访问网站的时候,会有403报错。
3. 条件使用正则表达式进行匹配
“~” 用正则来匹配(此处的正则区分大小写)
“~*”用正则来匹配(不区分大小写的正则)
"!~"与"~"相反
"!~*"与"!~*"相反
例子:
location / {
root html;
index index.html index.htm;
if ($http_user_agent ~ Chrome){
return 403;
}
}
当客户端浏览器为谷歌浏览器的时候,网站响应403错误。
location / {
root html;
index index.html index.htm;
if ($http_user_agent ~ Chrome){
rewrite ^.*$ /ie.html;
}
}
访问站点的时候,出现错误:
500 Internal Server Error
为什么呢?
因为我设置重定向到ie.html,当请求访问重定向的地址的时候,又是一个Chrome发起的请求,这是一个循环重定向。如何解决这个问题呢?
location / {
root html;
index index.html index.htm;
if ($http_user_agent ~ Chrome){
rewrite ^.*$ /ie.html; 默认使用的是
break; 必须使用break,不然会循环重定向
}
}
在正则表达式中,可以使用小括号对变量值进行截取,在花括号中使用$1...$9引用截取的值
if ($http_cookie ~* "id=([^;]+)(?:;|$)") { set $id $1; }
4. 条件中判断文件是否存在
-f:如果请求的文件存在,条件为true,如果请求的文件不存在,条件为false。
!-f:如果文件存在,条件为false;如果文件和目录都不存在,条件为false;如果文件不存在,但文件所在目录存在,条件为true。
5. 条件中判断目录是否存在
-d:如果请求的目录存在,条件为true,如果请求的目录不存在,条件为false。
!-d:如果目录存在,条件为false;如果目录和父目录都不存在,条件为false;如果目录不存在,但父目录存在,条件为true。
6. 条件中判断请求的目录或文件是否存在
-e:如果请求的目录或文件存在,条件为true,如果请求的目录或文件不存在,条件为false。
!-e:如果请求的文件和该文件所在路径上的目录都不存在,为true;否则为false。
7. 条件中判断请求的文件是否可执行
-x:如果请求的文件可执行,条件为true,否则为false。
!-x:如果请求的不可执行,条件为true,否则为false。
2. break语法
用于中断相同作用域中的其他nginx配置。
break可以使用在server,location,if块中。
location / {
if ($slow) {
set $id $1 处于break之前,配置有效
break;
limit_rate 10k; 处于break之后,配置无效
}
...... 其他nginx配置,处于break上一层作用域,配置有效
}
3. return语法
return code 返回给客户端HTTP状态码,0~999
return URL 返回给客户端URL
return [text] 返回给客户端的响应体内容
4. rewrite语法
rewrite regex replacement [flag];
regex 用于匹配URI的正则表达式。使用括号"()"标记要截取的内容
注意:rewrite指令接收到的URI为"/source",不包含"myweb.com"和"?agr=value1&agr2=value2"
replacement 匹配成功后用于替换URI中被截取内容的字符串。
replacement变量中支持Nginx全局变量的使用,常用的还有$uri和$args等。
flag 用来设置rewrite对URI的处理行为
last 大部分都使用这个flag
location / {
rewrite ^(/myweb/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 last;
rewrite ^(/myweb/.*)/audio/(.*)\..*$ $1/mp3/$2.ra last;
}
如果某URI在第二行匹配成功并处理,nginx服务器不会继续使用第3行的配置匹配和处理新的URI.
但是其他的location块会重新匹配和处理新的URI
break 匹配成功后,将中断匹配
location / {
rewrite ^(/myweb/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/myweb/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
}
如果某URI在第二行匹配成功并处理,nginx服务器将新的URI继续在该location块中使用第3行进行匹配和处理,不会将新的URI转向到其他location块,新的URI始终是在同一个location块中。
redirect 临时重定向URI,主要用在replacement变量不是以http://或者https://开头的情况下
permanent 永久重定向URI
5. rewrite_log指令
rewrite_log on | off; 是否开启URL重写日志的输出功能,默认为off,开启以后,以notice级别输出到error_log的日志文件中
6. set指令
set variable value; 设置一个新的变量
variable 使用$作为变量的第一个字符,不能与Nginx服务器的全局变量同名
value 可以是字符串,其他变量或变量的组合
4. Rewrite的使用
1. 域名跳转
1. 单个域名
server
{
listen 80;
server_name nacos.dev.zp.com;
access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
rewrite ^/ http://www.baidu.com/;
location / {
# add_header Access-Control-Allow-Origin *;
proxy_pass http://nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /devDist {
add_header Access-Control-Allow-Origin *;
root /website/demo.dev.zp.com;
index index.html;
}
}
2. 多个域名
server
{
listen 80;
server_name nacos.dev.zp.com nacos.dev.zp.net;
access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
if ($host ~ zp\.com)
{
rewrite ^(.*) http://www.baidu.com$1 permanent;
}
if ($host !='nacos.dev.zp.com') {
rewrite ^/(.*)$ http://www.baidu.com/$1 permanent;
}
location / {
# add_header Access-Control-Allow-Origin *;
proxy_pass http://nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /devDist {
add_header Access-Control-Allow-Origin *;
root /website/demo.dev.zp.com;
index index.html;
}
}
3. 三级域名
server
{
listen 80;
server_name nacos.dev.zp.com nacos1.dev.zp.com;
access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
if ($host ~ ^(.*)\.dev\.zp\.com)
{
rewrite ^(.*) http://www.baidu.com;
}
location / {
# add_header Access-Control-Allow-Origin *;
proxy_pass http://nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /devDist {
add_header Access-Control-Allow-Origin *;
root /website/demo.dev.zp.com;
index index.html;
}
}
4. 域名跳转到本地端口
upstream tomcat {
server 127.0.0.1:8080;
}
server {
listen 80;
server_name test.ceshi.com;
root /var/www/vhosts/ test.ceshi.com/;
location / {
proxy_pass http://tomcat ;
}
}
2. 域名镜像
1. 为整个网站做镜像
{
listen 80;
server_name nacos1.dev.zp.com;
access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
rewrite ^(.*) http://www.baidu.com$1 last;
}
{
listen 80;
server_name nacos2.dev.zp.com;
access_log /usr/local/nginx/logs/nacos.dev.zp.com.log nacos_log;
rewrite ^(.*) http://www.baidu.com$1 last;
}
2. 为某个子目录做镜像
location ^~ /a {
add_header Access-Control-Allow-Origin *;
rewrite ^/a(.*) http://www.baidu.com$1 last;
}
location ^~ /b {
add_header Access-Control-Allow-Origin *;
rewrite ^/b(.*) http://www.baidu.com$1 last;
}
3. 当访问http://abc.wangshibo.com跳转到http://www.wangshibo.com/wangshibo/abc/
方法一:这种方法浏览器地址会变www.wangshibo.com/wangshibo/abc
server {
listen 80;
server_name www.wangshibo.com;
location / {
root /data/wangshibo;
index index.html;
}
}
server {
listen 80;
server_name *.wangshibo.com;
if ( $http_host ~* "^(.*)\.wangshibo\.com$") {
set $domain $1;
rewrite ^(.*) http://www.wangshibo.com/wangshibo/$domain/ break;
}
}
方法二:当访问http://abc.wangshibo.com/*跳转到http://www.wangshibo.com/wangshibo/abc/*
server {
listen 80;
server_name *.wangshibo.com;
root /usr/local/www;
#这是里可以加多个目录,如果不加目录,会无法访问到abc.wangshibo.com/目录下的文件,如图片目录/images
location ~ ^/(wangshibo|images|styles)/
{
proxy_redirect off;
proxy_set_header Host www.wangshibo.com;
proxy_pass http://192.168.1.2:8080;
}
location / {
set $domain default;
if ( $http_host ~* "^(.*)\.wangshibo\.com$") {
set $domain $1;
}
rewrite ^/(.*) /wangshibo/$domain/$1 last;
}
access_log off;
}
4. 访问一个域名http://yangjianbo.com自动跳转http://www.yangjianbo.com
1) 首先要保证不加www和加www的域名都要解析出来。
在DNS里添加yangjianbo.com和www.yangjianbo.com的解析,比如解析到111.110.11.18
@ IN A 111.110.11.18
www IN A 111.110.11.18
解释:
A记录解析yangjianbo.com到111.110.11.18地址上,前面加@或者留空(留空默认就是@)
A记录解析www.yangjianbo.com到111.110.11.18地址上,前面加www
2)nginx配置不加www自动跳转到www的域名访问(80或443都一样),有下面两种方法实现:
方法一:
在conf/vhost/yangjianbo.conf文件中配置:
server {
listen 80;
server_name www.yangjianbo.com yangjianbo.com;
index index.jsp index.html index.php index.htm;
root /var/www/html;
access_log /data/nginx/logs/www.yangjianbo.com-access.log main;
error_log /data/nginx/logs/www.yangjianbo.com-error.log;
if ($host = "yangjianbo.com") {
rewrite ^/(.*)$ http://www.yangjianbo.com permanent;
}
}
方法二(官方推荐这一种nginx的301跳转方法)
在conf/vhost/yangjianbo.conf文件中配置:
server {
listen 80;
server_name yangjianbo.com;
return 301 http://www.yangjianbo.com$request_uri;
}
server {
listen 80;
server_name www.yangjianbo.com;
index index.jsp index.html index.php index.htm;
root /var/www/html;
access_log /data/nginx/logs/www.yangjianbo.com-access.log main;
error_log /data/nginx/logs/www.yangjianbo.com-error.log;
}
5. 目录合并
比如将/wang-123-456-789.html指向wang/123/456/wangshow_789.html
[root@test-huanqiu ~]# cat /usr/local/nginx/conf/vhosts/test.conf
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/wang-([0-9]+)-([0-9]+)-([0-9]+)\.html$ http://www.wangshibo.com/wang/$1/$2/wangshow_$3.html last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
这样访问http://www.wangshibo.com/wang-123-456-789.html就会跳转到http://www.wangshibo.com/wang/123/456/wangshow_789.html
6. 访问的目标文件和目录不存在的时候重定向跳转
server {
listen 80;
server_name www.wangshibo.com;
if (!-e $request_filename) {
rewrite ^/ http://www.wangshibo.com/sorry.html ;
}
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
7. 将站点根目录下某个目录指向二级目录
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/([0-9a-z]+)pc/(.*)$ http://www.wangshibo.com/ops/$1/$2 last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
这样,访问http://www.wangshibo.com/huanqiupc的时候就会跳转到http://www.wangshibo.com/ops/huanqiu/
注意:上面的配置中的last修改为permanent或redirect都可以
8. 访问http://www.wangshibo.com/g/4HG45SkZ 实际访问地址跳转为 http://110.10.88.99:8081/qun/share/view?code=4HG45SkZ
upstream g_server {
keepalive 64;
server 110.10.88.99:8081 max_fails=2 fail_timeout=5 weight=100;
}
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/bcloud.(swf|html|js)(.*)$ http://hehe.wangshibo.com/bcloud.$1$2 last;
root /home/web/www;
location ~ \.apk$ {
max_ranges 0;
}
location ^~ /g {
proxy_redirect off;
proxy_set_header Host $host;
# proxy_set_header Host $host:$remote_port;
# proxy_set_header REMOTE_PORT $remote_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 1G;
client_body_buffer_size 256k;
proxy_connect_timeout 30;
proxy_send_timeout 30;
proxy_read_timeout 600;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_temp_file_write_size 64k;
proxy_pass http://g_server;
#rewrite "/g/(.*$)" www.wangshibo.com/qun/share/view?code=$1 break;
rewrite "/g/(.*$)" /qun/share/view?code=$1 break;
}
}
9. 访问http://www.wangshibo.com/thumb/transcode 实际访问地址为 http://120.170.190.99:28080/transcode/thumb/transcode
upstream thumb {
keepalive 64;
server 120.170.190.99:28080 max_fails=2 fail_timeout=5 weight=100;
}
server {
listen 80;
server_name www.wangshibo.com ;
root /home/web/www;
location ^~ /thumb {
proxy_pass http://thumb;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for;
client_max_body_size 1G;
client_body_buffer_size 256k;
proxy_connect_timeout 30;
proxy_send_timeout 30;
proxy_read_timeout 60;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_temp_file_write_size 64k;
rewrite "^/(.*)$" /transcode/$1 break;
}
}
10. 访问http://www.wangshibo.com/wangshibo/ops就会跳转到http://www.wangshibo.com/ops/wangshibo
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/wangshibo/(.*)$ http://www.wangshibo.com/$1/wangshibo last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
11. 访问http://www.wangshibo.com/ops/web 跳转到 http://www.wangshibo.com/web/ops/web/
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/ops/(.*)$ http://www.wangshibo.com/$1/ops/$1 break;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}
12. 访问http://www.wangshibo.com/wang/123 实际访问地址跳转为 http://www.hehe.com/qun/share/view?code=123
server {
listen 80;
server_name www.wangshibo.com;
rewrite ^/wang/(.*)$ http://www.hehe.com/qun/share/view?code=$1 last;
root /var/www/html;
index index.html index.php index.htm;
access_log /usr/local/nginx/logs/image.log;
}

浙公网安备 33010602011771号