Nginx-rewrite

主要实现url地址重写,url地址跳转

rewrite应用场景

image-20250428164959737.png

Rewrite重写模块

if条件判断指令

需求:匹配nginx请求中包含id=2356的,然后代理到10.16.3.5的8080端口
[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_if.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code;
		
	location / {
		index  index.html;
	
		if ($request_uri ~ 'id=2356') {
			proxy_pass http://10.16.3.5:8080;
		}
	}
}
set设定变量

需求:通过user_agent(header)拦截压测测试工具
[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_set.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code;
		
	location / {
		index  index.html;
	
		if ($http_user_agent ~* "curl|firefox") {
			set $deny_user_agent 1;
			}
		if ($deny_user_agent = 1) {
			return 403;
			}
			
	}
}
return返回数据指令
   location / {
            default_type text/html;
            if (\$http_user_agent ~* "iphone|android|ipad") {
                    proxy_pass http://phone;
            }
            if ($http_user_agent ~* "MSIE|Trident") {
                    #return 403; (返回403状态码)
                    return 200 'Please Change Browser'; (返回请更换浏览器)
                    #return 302 'https://www.firefox.com.cn/download/thanks/'; (自动跳转下载其他浏览器)
            }
            proxy_pass http://pc;
            include proxy_params;
    }
Rewrite重写Flag

#flag

last #本条规则匹配完成后,继续向下匹配新的location URI规则

break #本条规则匹配完成即终止,不再匹配后面的任何规则

redirect #返回302临时重定向,地址栏会显示跳转后的地址

permanent #返回301永久重定向,地址栏会显示跳转后的地址

break(通常用于停机维护)

[root@web01]# cat url.oldxu.net.conf

server {
	listen 80;
	server_name url.oldxu.net;
	root /code;
	

​	location / {
​		rewrite /1.html /2.html break;
​		rewrite /2.html /3.html;
​	} 

​	location /2.html {
​		rewrite /2.html /a.html;
​	} 

​	location /3.html {
​		rewrite /3.html /b.html;
​	}
}

#测试结果:当请求/1.html,最终会访问/2.html
#因为:在location{}内部,遇到break,本
location{}内以及后面的所有location{}内的所有指令都不再执行。

last(通常用于将动态请求改为静态地址)

[root@web01]# cat url.oldxu.net.conf

server {
	listen 80;
	server_name url.oldxu.net;
	root /code;
	

​	location / {
​		rewrite /1.html /2.html last;
​		rewrite /2.html /3.html;
​	} 

​	location /2.html {
​		rewrite /2.html /a.html;
​	} 

​	location /3.html {
​		rewrite /3.html /b.html;
​	}
}

#测试结果:当请求/1.html,最终会访问/a.html
#因为:在location{}内部,遇到last,本location{}内后续指令不再执行,
#而重写后的url会对所在的server{}标签重新发起请求,从头到尾匹配一遍规则,哪个匹配则执行哪个

附加:break与last的区别

当 rewrite 规则遇到 break 后,本 location{} 与其他 location{} 的所有规则都不执行。

当 rewrite 规则遇到 last 后,本 location{} 里后续规则不执行,但重写后的url 会再次从头开始匹配所有 Location,哪个匹配执行哪个。

redirect(302临时跳转,对旧网站无影响,新网站会继承排名)

[root@web01]# cat url.oldxu.net.conf

server {
	listen 80;
	server_name url.oldxu.net;
	root /code;
	

​	location / {
​		rewrite /1.html /2.html redirect;
​		rewrite /2.html /3.html;
​	}
}
permanent(301永久跳转,新网站继承排名,旧网站排名会清空)

[root@web01]# cat url.oldxu.net.conf

server {
	listen 80;
	server_name url.oldxu.net;
	root /code;
	

​	location / {
​		rewrite /1.html /2.html permanent;
​		rewrite /2.html /3.html;
​	}
}

Rewrite跳转实例

1、根据用户浏览器请求头中携带的语言调度到不同的页面

mkdir /code4

mkdir /code4/zh

mkdir /code4/en

echo "zh..." > /code4/zh/index.html

echo "en..." > /code4/en/index.html

[root@web01 ~]# vim /etc/nginx/conf.d/url.zjh.net_language.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
		
	location / {
		if ($http_accept_language ~* "zh|zh-cn") {
			set $language zh;
		}	
		if ($http_accept_language ~* "en|jp") {
			set $language en;
		}
	
	rewrite ^/$ /$language;
	}
}
2、根据用户不同的设备调度到不同的页面中

[root@web01 ~]# mkdir /code4/m
[root@web01 ~]# echo "phone..." > /code4/m/index.html

[root@web01 ~]# echo "www..." > /code4/index.html

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_agent.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
		
	location / {
		if ($http_user_agent ~* "android|iphone|ipad") {
			rewrite ^/$ /m redirect;
	
		}
	}
}
3、根据用户不同的设备调度到不同的域名中

[root@web02 ~]# cat /etc/nginx/conf.d/m.zjh.net.conf

server {
	listen 80;
	server_name m.zjh.net;
	root /code4;

	location / {
		index index.html;
	}
}

[root@web02 ~]# echo "web02..." > /code4/index.html

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_mobile.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
		

	location / {
		if ($http_user_agent ~* "android|iphone|ipad") {
			rewrite ^/$ http://m.zjh.net redirect;
	
		}
	}
}
4、用户通过http协议请求时自动跳转到https协议访问
server {
        listen 80;
        server_name url.zjh.net;
        root /code4;

      #  可使用的变量名
      #  $http_host
      #  $server_name
      #  $host
         rewrite ^(.*)$ https://$http_host$1 redirect;
      #  return 302 https://$http_host$request_uri;(第二种写法)
}
server {
        listen 443;
        server_name url.zjh.net;
}
5、网站维护过程中,用户访问网站时自动重定向到一个维护页面

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_wh.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	#维护页面开关,需要启用时把注释删掉启用
	#rewrite ^(.*)$ /wh.html break;
	
	location / {
		index index.html;
	}
}

[root@web01 ~]# echo "维护中..." > /code4/wh.html

6、当网站遇到403 404 502时,自动跳转到临时维护的静态页面

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_404.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	}
	
	error_page 404 403 502 500 503 504 @error_wh;
	location @error_wh {
		rewrite ^(.*)$ /wh.html break;
	}
}

[root@web01 ~]# echo "维护中..." > /code4/wh.html

7、公司在停机维护时,指定ip地址能正常访问,其他ip地址跳转到维护页面

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_ip.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
	#将IP变量设定为0
	set $ip 0;
	#将指定机器的IP变量设定为1,则可以正常访问
	if ($remote_addr ~ "10.0.0.1|10.0.0.2") {
		set $ip 1;
		}
	#其余非指定IP的机器将IP变量设定为0,跳转到维护页面
	if ($ip = 0) {
		rewrite ^(.*)$ /wh.html break;
		}
	}

}
8、公司网站后台/admin只允许公司的公网IP访问,其余IP全部返回状态值500,或跳转会首页

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_admin.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
	set $ip 0;
	if ($remote_addr ~ "10.0.0.1|10.0.0.2") {
		set $ip 1;
		}
	
	if ($ip = 0) {
		rewrite ^(.*)$ /wh.html break;
		}
	}
	
	location /admin {
		limit_rate 100k;
		#设定IP变量为0
		set $ip 0;
		#设定公司的公网地址为1,允许访问admin目录
		if ($remote_addr ~ 10.0.0.1) {
			set $ip 1;
			}
		#其余IP变量设定为0,返回状态码404,或返回主页
		if ($ip = 0) {
			#return 404;
			return 302 http://$http_host;
			}			
	}

}
9、当用户请求url.zjh.net/bbb时,实际是在请求http://demo:27610/test/bbb(最后一级域,放在uri的第一个路径,实际请求的uri,写到第二级路径)

image-20250506083435952.png

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_domain.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
		if ($http_host ~* (.*)\.(.*)\.(.*)) {
			set $domain $1;
		}
	
		rewrite ^(.*)$ http://demo:27610/$domain$request_uri redirect;
	}

}
10、现有两台服务器,当用户访问http://url.oldxu.net/index.php?r=survey/index/sid/613192/lang/zh-Hans,若访问资源为/index.php?r=survey...时,跳转到另一台服务器http://sur.oldxu.net/index.php?r=survey/index/sid/613192/lang/zh-Hans
请求的域名:http://url.oldxu.net/index.php?r=survey/index/sid/613192/lang/zh-Hans
替换后域名:http://sur.oldxu.net/index.php?r=survey/index/sid/613192/lang/zh-Hans
(只替换域名,后面的uri部分原封不动)

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_uri.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
		if ($args ~* "r=survey") {   #args表示uri中问号后面的参数
			rewrite ^(.*)$ http://sur.zjh.net/$request_uri? redirect;  
			#问号表示丢弃原始请求的uri参数,如果没添加问号会导致"Location: 					http://sur.zjh.net//index.php?r=survey/index/sid/613192/lang/zh-Hans r=survey/index/sid/613192/lang/zh-Hans(uri问号部分参数重复)"
		}
	}

}
11、当用户访问http://url.zjh.net/?id=2时,替换为http://url.zjh.net/id/2.html

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_id.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
		if ($args ~ "id") {
			set $OK 1;
		}
	
		if ($args ~ (.*)=(.*)) {
			set $id $1;
			set $num $2;
		}
	
		if ($OK = 1) {
			rewrite ^(.*)$ http://http://$http_host/$id/$num.html? last;
		}
	}

}

12、禁止搜索引擎爬取网站(通过user_agent防止搜索引擎的爬取)

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_agent.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	
		if ($http_user_agent ~* "YisouSpider|baiduSpider|YoudaoBot") {
			return 403;
		}
	}

}

[root@web02 ~]# curl -L -I -A "yisouspider" -HHost:url.zjh.net http://10.0.0.7
HTTP/1.1 403 Forbidden
Server: nginx/1.26.1
Date: Wed, 07 May 2025 03:07:44 GMT
Content-Type: text/html; charset=utf8,gbk
Content-Length: 153
Connection: keep-alive

13、禁止站点资源被盗用

[root@web01 ~]# cat /etc/nginx/conf.d/url.zjh.net_tou.conf

server {
	listen 80;
	server_name url.zjh.net;
	root /code4;
	charset utf8,gbk;

	location / {
		index index.html;
	}
	
	location ~ .*\.(jpg|png|jpeg|gif)$ {
		valid_referers none blocked *.zjh.net; (允许通过的域名白名单)
		
		if ($invalid_referer) {
		#	return 403;
			rewrite ^(.*)$ /error.jpg break;  (被盗图时返回自定义的图片)
		}
	}

}