rewrite跳转
3621 字
18 分钟
rewrite跳转

rewrite跳转
[TOC]
Nginx实现四层转发

暴漏lb01的公网IP(10.0.0.5),用户只需要连接lb01即可,它通过私网与后台web集群通信负载均衡是专门给谁提供服务的?---->用户'通过四层代理转发连接后台web'# Nginx是”假四层“代理转发我们去连接lb01的时候会去占用负载均衡的性能# 后面我们会通过一个跳板机去管理后台web集群
我们访问负载均衡的5555端口,转发到172.16.1.7:22端口# 负载均衡10.0.0.5[root@lb01 ~]#cd /etc/nginx[root@lb01 nginx]#vim nginx.conf# 编辑主配置文件...events { worker_connections 1024;}# 从下面开始粘贴stream { upstream web01 { server 172.16.1.7:22; } server { listen 5555; proxy_pass web01; # 四层转发,没有http:// }}======================# 注意四层转发需要在http区块外面配置======================http { ... include /etc/nginx/conf.d/*.conf; # 它包含着我们子配置文件}[root@lb01 nginx]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@lb01 nginx]#systemctl restart nginx
[root@web01 ~]#ip addr show# 查看web01网卡信息2: eth0: .... inet 10.0.0.7/24 brd 10.0.0.2553: eth1: .... inet 172.16.1.7/24 brd 172.16.1.255[root@web01 ~]#ifdown eth0# 关闭eth0网卡,这个时候我们的Xshell就连接不上了Connecting to 10.0.0.7:22...Could not connect to '10.0.0.7' (port 22): Connection failed.
#xshell远程连接测试[C:\~]$ ssh 10.0.0.5 5555Connecting to 10.0.0.5:5555...[root@web01 ~]#hostname -I172.16.1.7# 成功跳转连接到web01
'同理我们也可以把web02加上去'[root@lb01 nginx]#vim nginx.confstream { upstream web01 { server 172.16.1.7:22; } server { listen 5555; proxy_pass web01; } upstream web02 { server 172.16.1.8:22; } server { listen 6666; # 负责监听172.16.1.5:6666端口 proxy_pass web02; }}[root@lb01 nginx]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@lb01 nginx]#nginx restart nginxnginx: invalid option: "restart"[root@lb01 nginx]#systemctl restart nginx
# windows 测试[C:\~]$ ssh 10.0.0.5 6666Connecting to 10.0.0.5:6666...[root@web02 ~]#hostname -I10.0.0.8 172.16.1.8# 用户访问负载均衡的6666端口转发后端web02的22端口Rewrite
什么是Rewrite?就是把传入web的请求重定向到其他url的过程核心作用:实现URL地址重写、跳转(301/302 重定向)、伪静态化等,提升用户体验、安全性和SEO优化# SEO优化,下面介绍使用场景
| 场景 | 描述 | 示例 |
|---|---|---|
| 地址跳转 | 将用户访问的旧域名或路径自动跳转到新地址 | www.kpyun.com → new.kpyun.com |
| 协议跳转 | 强制 HTTP 请求跳转为 HTTPS,提升安全性 | http://kpyun.com → https://kpyun.com |
| 伪静态 | 将动态 URL(含参数)伪装成静态路径,便于隐藏参数和 SEO | /user.php?id=123 → /user/123.html |
| SEO 优化 | 使用简洁、语义化的 URL 便于搜索引擎录入和排名 | /product?id=5 → /products/shoes |
重写VS重定向
| 对比项 | 重写 | 重定向 |
|---|---|---|
| 发生位置 | 服务器内部(对客户端透明) | 服务器 → 客户端 → 新地址(需浏览器二次请求) |
| URL 是否改变 | ❌ 浏览器地址栏 不变 | ✅ 浏览器地址栏 变为新 URL |
| curl命令影响 | 无影响,URL不变 | 有影响,直接返回状态码3xx |
| HTTP 状态码 | 通常返回 200 OK(原始请求成功) | 返回 3xx(如 301 永久、302 临时) |
| 请求次数 | 仅 1 次 请求 | 2 次 请求(先访问原 URL,再跳转到新 URL) |
| 用途 | 伪静态、隐藏真实路径、内部路由转发 | 域名迁移(换域名)、协议升级(HTTP→HTTPS)、页面永久移动 |
| 性能影响 | 更高效(无额外网络往返) | 略低效(多一次 HTTP 请求) |
🌰 举例说明
- 重写
用户访问:https://example.com/user/123
服务器内部将其重写为:/user.php?id=123
✅ 用户看到的仍是 /user/123,但实际由动态脚本处理
- 浏览器地址栏不变,对客户端透明
- 重定向
用户访问:http://example.com
服务器返回 301,告诉浏览器跳转到:https://example.com
✅ 浏览器地址栏从 http 变为 https
flag标记
'Rewrite标记Flag'rewrite指令根据表达式来重定向URL,或者修改字符串,可以应用于server,location,if环境下,每行rewrite指令最后跟一个flag标记,支持的flag标记有如下表格所示:| 标志 | 作用 |
|---|---|
last | 停止当前 rewrite 处理,使用重写后的新 URI 重新搜索 location |
break | 停止 rewrite,但不再重新匹配 location,直接使用当前 URI 处理 |
redirect | 返回 302 临时 重定向,地址栏会显示跳转后的地址 |
permanent | 返回 301 永久 重定向,地址栏会显示跳转后的地址 |
⚠️ 注意:
如果
重写的目标是 外部URL(如https://other.com)但没有加
redirect或permanent,Nginx 会报错( 因为不能内部重写到外部域名 )要跨域“代理”内容且地址栏不变,应该用
proxy_pass,而不是rewrite
last和break
'默认不加标签和加这俩标签,本质上都是重写,不改变URL'# 故使用curl命令即可进行测试
# web01中测试即可[root@web01 ~]#cd /etc/nginx/conf.d/[root@web01 conf.d]#vim test.confserver { listen 80; server_name test.kpyun.com; root /code/test; index index.html;
location / { rewrite /1.html /2.html; rewrite /2.html /3.html; }
location /2.html { rewrite /2.html /a.html; }
location /3.html { rewrite /3.html /b.html; }}# 访问test.kpyun.com/1.html 返回的是b.html中内容# 访问test.kpyun.com/2.html 返回的是a.html中内容[root@web01 conf.d]#rm -rf /code/test/*[root@web01 conf.d]#echo web01... > /code/test/index.html[root@web01 conf.d]#echo 222 > /code/test/2.html[root@web01 conf.d]#echo aaa > /code/test/a.html[root@web01 conf.d]#echo bbb > /code/test/b.html[root@web01 conf.d]#echo 333 > /code/test/3.html[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl restart nginx[root@web01 conf.d]#vim /etc/hosts10.0.0.7 test.kpyun.com[root@web01 conf.d]#curl test.kpyun.comweb01...[root@web01 conf.d]#curl test.kpyun.com/1.htmlbbb[root@web01 conf.d]#curl test.kpyun.com/2.htmlaaa'目前rewrite就是这么来跳转的,这就是它默认的匹配规则!'# 如果我们在他后面加上tag后,就可以控制它的匹配
1)测试last标记[root@web01 conf.d]#vim test.confserver { listen 80; server_name test.kpyun.com; root /code/test; index index.html;
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; }}[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx[root@web01 conf.d]#curl test.kpyun.com/1.htmlaaa# 访问到1.html跳转到2.html后,停止rewrite,使用新的 URI 重新搜索 `location`# 所以就匹配到了aaa
2)测试break标记[root@web01 conf.d]#vim test.confserver { listen 80; server_name test.kpyun.com; root /code/test; index index.html;
location / { rewrite /1.html /2.html break; # 停止向后匹配返回2.html rewrite /2.html /3.html; }...[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl restart nginx[root@web01 conf.d]#curl test.kpyun.com/1.html222# 后续也不继续搜索 `location`重定向
'下面的例子是关于域名的迁移'HTTP 301 # 永久重定向HTTP 302 # 临时重定向✅浏览器地址栏变为新 URL# 正是因为变成了新的URL,你用curl命令行不通(它会固定URL),得用浏览器# 浏览器的地址栏会发生变化2次请求(先访问原URL,再跳转到新URL)永久重定向(301)

# 永久的更换域名了,用户只记得老的域名
用户只会在第一次请求源站,当它第二次再访问的时候; 不会请求源站,直接通过缓存请求 `www.oldgirl.com` (新的站点)
1.只要用户访问过一次源站,即使源站挂掉,也不影响客户端访问新的站点# 因为在浏览器已经缓存下来了2.浏览器有缓存,但是新站点挂掉了,只有手动清缓存才能访问老站点(缺点)'permanent-301-永久跳转'[root@web01 ~]#cd /etc/nginx/conf.d/[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location /re { # 得匹配到/re,也就是rewrite.kpyun.com/re rewrite ^(.*)$ http://www.baidu.com permanent; # 前面是一个正则,任何的URL,都跳转 # 空格 permanent }}nginx -tsystemctl reload nginx
浏览器访问 rewrite.kpyun.com/re 跳转到百度页面1)地址栏发生变化2)只要请求过一次,用户浏览器就有了缓存 # 测试把源站点关闭,依旧能够跳转百度[root@web01 conf.d]#systemctl stop nginx再次访问 rewrite.kpyun.com/re 依旧跳转到百度页面# 缓存在发力'如果你换一个浏览器,或者清理掉缓存,就访问不到了'[root@web01 conf.d]#curl rewrite.kpyun.com/re<head><title>301 Moved Permanently</title></head># 因为地址栏会发生变化,而你curl没有办法变化URL,故直接返回状态码301return跳转
另一种临时跳转方式:'return'# 常见格式:返回状态码+新的url地址[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location /re { #rewrite ^(.*)$ http://www.baidu.com permanent; return 301 http://www.baidu.com; }}nginx -tsystemctl reload nginx临时重定向(302)

'每次都会请求源站'1.如果源站挂掉,则用户无法访问新的站点2.如果新的站点挂掉,则自动请求源站(优点)'redirect-302-临时跳转'[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location /re { rewrite ^(.*)$ http://www.baidu.com redirect; #这次是 空格 redirect }}[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx
# Windows做hosts解析10.0.0.7 rewrite.kpyun.com
浏览器访问 rewrite.kpyun.com/re 跳转到百度页面1)地址栏发生变化2)每次得先请求源站,才可以跳转到百度 # 测试把源站点关闭,无法跳转百度# 用户---->源站---->返回百度---->用户---->百度
另一种临时跳转方式:location /re { return 302 http://www.baidu.com; }nginx -tsystemctl reload nginx再次访问 rewrite.kpyun.com/re 依旧跳转到百度页面跳转案例
# 我们用域名跳转的比较少,更多的是资源的跳转!
[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location /abc/1.html { rewrite ^(.*)$ /ccc/bbb/2.html; }} # 从/abc/1.html跳转到/ccc/bbb/2.html # 这次后面没有跟任何的标签,是默认的跳转 '更准确来说是重写,浏览器地址没有发生变化' # 绝对路径是/code/re/ccc/bbb/2.html[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx[root@web01 conf.d]#mkdir -p /code/re/ccc/bbb/[root@web01 conf.d]#echo 222... > /code/re/ccc/bbb/2.html[root@web01 conf.d]#vim /etc/hosts10.0.0.7 rewrite.kpyun.com[root@web01 conf.d]#curl rewrite.kpyun.com/abc/1.html222...# 用户访问/abc/1.html实际上真实访问的是/ccc/bbb/2.html
浏览器输入:rewrite.kpyun.com/abc/1.html'地址栏没有发生变化'
更改一下配置location /abc/1.html { return 302 /ccc/bbb/2.html; }# 如果你写的是return 302...(临时重定向)nginx -tsystemctl reload nginx[root@web01 conf.d]#curl rewrite.kpyun.com/abc/1.html<head><title>302 Found</title></head># 地址栏无法改变,故返回状态码[root@web01 conf.d]#ll /code/re/abc/1.htmlls: cannot access '/code/re/abc/1.html': No such file or directory# 现在是没有这个目录文件[root@web01 conf.d]#mkdir /code/re/abc/[root@web01 conf.d]#echo 111 > /code/re/abc/1.html[root@web01 conf.d]#ll /code/re/abc/1.html-rw-r--r-- 1 root root 4 Mar 1 21:26 /code/re/abc/1.html[root@web01 conf.d]#curl rewrite.kpyun.com/abc/1.html<head><title>302 Found</title></head># 即使有,也不会正常返回,因为服务器给用户返回的是/code/re/ccc/bbb/2.html
浏览器再次访问'地址栏改变'
正则表达式匹配
'参考笔记Nginx02中的location匹配优先级'1)案例[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location ~ /(.*abc)$ { # 匹配以abc字符结尾的URI rewrite ^(.*)$ /ccc/bbb/2.html; # 后面没有加任何标签,普通的跳转,地址栏不变 }}nginx -tsystemctl reload nginx[root@web01 conf.d]#curl rewrite.kpyun.com/no/not_page/hhhabc222...# 我的服务器上并没有这些目录和文件,只要是以abc结尾就能够跳转
2)案例[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location ~ /2014/ { rewrite ^/2014/(.*)$ /2026/$1; } # 类似于后向引用 # 用户访问/2014/...实际上真实访问的是/2026/...}nginx -tsystemctl reload nginx[root@web01 conf.d]#mkdir -p /code/re/2026/ccc/bbb[root@web01 conf.d]#echo hhhh > /code/re/2026/ccc/bbb/hh.html[root@web01 conf.d]#curl rewrite.kpyun.com/2014/ccc/bbb/hh.htmlhhhh# 表面访问的是2014/文件夹下的内容,实际把2014换为了2026,后面的都不变[root@web01 conf.d]#ll -d /code/re/2014ls: cannot access '/code/re/2014': No such file or directory# 实际上就没有2014这个目录
3)案例[root@web01 conf.d]#vim re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re;
location ~ /2014/ { rewrite ^/2014/(.*)/(.*)$ /2026/$2/$1; } # $2和$1他们之间的位置可以发生自由变换 # ^/(.*)/(.*)/(.*)$ 不能这样写!!!前面必须是一个确切的路径}nginx -tsystemctl reload nginx[root@web01 conf.d]#curl rewrite.kpyun.com/2014/bbb/hh.html/ccchhhh[root@web01 conf.d]#cat /code/re/2026/ccc/bbb/hh.htmlhhhh
错误页匹配
4)案例# 错误页面跳转'这里可以联想参考Nginx02中的error_page'# 上面笔记是单个状态码页面进行拦截,下面进行的是整个状态码的拦截![root@web01 conf.d]# cat re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re; error_page 403 404 @error_test; # 如果遇到这些错误的状态码,重新发起一个请求 # 这些状态码,空格隔开
location @error_test { # 接受错误的请求 rewrite ^(.*)$ /error.html break; # 跳转到一个专门的错误页 # 空格 break }}[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx[root@web01 conf.d]#echo index > /code/re/index.html[root@web01 conf.d]#echo 'This is a error page' > /code/re/error.html[root@web01 conf.d]#curl rewrite.kpyun.comindex[root@web01 conf.d]#curl rewrite.kpyun.com/ddd/eeeThis is a error page# 访问一个不存在的页面,打印输出...[root@web01 conf.d]#tail -1 /var/log/nginx/error.log2026/03/01 17:35:49 [error] 3795#3795: *435 open() "/code/re/ddd/eee" failed (2: No such file or directory), client: 10.0.0.7, server: rewrite.kpyun.com, request: "GET /ddd/eee HTTP/1.1", host: "rewrite.kpyun.com"[root@web01 conf.d]#tail -1 /var/log/nginx/access.log10.0.0.7 - - [01/Mar/2026:17:35:49 +0800] "GET /ddd/eee HTTP/1.1" 404 21 "-" "curl/7.71.1" "-"# 拦截的是404状态码来源IP地址匹配
5)案例# 在请求域名后携带args参数需求分析: 1.正常用户访问rewrite.kpyun.com,则直接返回首页内容 2.如果是公司内部特定用户访问,则在域名后面加上&showoffline=1# 假设它的网络IP地址是10.0.0.1# 至于后面的参数可以理解为开发的需求当我们访问一个域名的时候默认携带args参数,只不过默认为空;现在开发的需求是让它带上一个特定的参数&showoffline=1[root@web01 conf.d]# cat re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re; index index.html;
if ($remote_addr = 10.0.0.1) { # 如果来源IP是10.0.0.1 set $args "&showoffline=1"; # 设置参数 rewrite ^(.*)$ http://rewrite.kpyun.com$1; # $1后向引用(.*) # 不改变用户访问的地址,只不过是重新访问了一遍 # 而这一遍,设置了特定的参数 }}-----------------------------set:用于自己创建变量或者修改Nginx变量1)shell写法:flag=666echo ${flag}
2)nginx中set写法set $变量 值;set $flag 666;'赋值或者使用都要加上$符号'-----------------------------[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx
# 别的IP地址浏览器访问,还是默认页面index[root@web01 conf.d]#hostname -I10.0.0.7 172.16.1.7[root@web01 conf.d]#curl rewrite.kpyun.comindex
浏览器测试访问rewrite.kpyun.com# IP地址是10.0.0.1'自动携带参数 &showoffline=1'
6)案例网站维护,指定IP正常访问,其他IP跳转维护页面# 公司业务停机维护
[root@web01 conf.d]# cat re.confserver { listen 80; server_name rewrite.kpyun.com; root /code/re; index index.html; set $flag 0; # 设置一个开关,默认为0
if ($remote_addr = 10.0.0.1){ set $flag 1; # 如果客户端IP是10.0.0.1则重新赋值为1 }
if ($flag = 0){ rewrite (.*) /wait.html break; # 正常用户访问,跳转维护页面 }}[root@web01 conf.d]#nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@web01 conf.d]#systemctl reload nginx[root@web01 conf.d]#echo '网站维护中ing...' > /code/re/wait.html[root@web01 conf.d]#curl rewrite.kpyun.com网站维护中ing...# 本地测试
浏览器测试访问rewrite.kpyun.com# IP地址是10.0.0.1返回的默认首页index
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
Tomcat动静分离
Web服务Tomcat动静分离与多端适配实战,通过Redis共享Session、Nginx正则分发及User-Agent路由
2
搭建企业内部yum仓库
Web服务企业内网YUM私有仓库搭建,使用createrepo+Nginx实现RPM包统一管理与离线快速分发
3
Keepalived 高可用
Web服务Keepalived高可用集群实战,讲解VRRP原理、主备部署、脑裂处理及Nginx健康检查自动切换
4
https证书部署
Web服务HTTPS证书部署与TLS加密实战,涵盖加密原理、自签名与真实证书配置及SSL参数优化
5
Nginx性能优化
Web服务Nginx性能优化全面指南,涵盖压力测试、内核调优、缓存压缩、防盗链与CPU亲和绑定
随机文章随机推荐



