rewrite跳转

3621 字
18 分钟
rewrite跳转

rewrite跳转#

[TOC]


Nginx实现四层转发#

image-20260224141533280
image-20260224141533280

Terminal window
暴漏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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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.255
3: 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 5555
Connecting to 10.0.0.5:5555...
[root@web01 ~]#hostname -I
172.16.1.7
# 成功跳转连接到web01
'同理我们也可以把web02加上去'
[root@lb01 nginx]#vim nginx.conf
stream {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@lb01 nginx]#nginx restart nginx
nginx: invalid option: "restart"
[root@lb01 nginx]#systemctl restart nginx
# windows 测试
[C:\~]$ ssh 10.0.0.5 6666
Connecting to 10.0.0.5:6666...
[root@web02 ~]#hostname -I
10.0.0.8 172.16.1.8
# 用户访问负载均衡的6666端口转发后端web02的22端口

Rewrite#

Terminal window
什么是Rewrite?
就是把传入web的请求重定向到其他url的过程
核心作用:实现URL地址重写、跳转(301/302 重定向)、伪静态化等,提升用户体验、安全性和SEO优化
# SEO优化,下面介绍

使用场景#

场景描述示例
地址跳转将用户访问的旧域名或路径自动跳转到新地址www.kpyun.comnew.kpyun.com
协议跳转强制 HTTP 请求跳转为 HTTPS,提升安全性http://kpyun.comhttps://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 请求)

🌰 举例说明

  1. 重写

用户访问:https://example.com/user/123 服务器内部将其重写为:/user.php?id=123 ✅ 用户看到的仍是 /user/123,但实际由动态脚本处理

  • 浏览器地址栏不变,对客户端透明

  1. 重定向

用户访问:http://example.com 服务器返回 301,告诉浏览器跳转到:https://example.com ✅ 浏览器地址栏从 http 变为 https

flag标记#

Terminal window
'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

    但没有加 redirectpermanent,Nginx 会报错( 因为不能内部重写到外部域名

  • 要跨域“代理”内容且地址栏不变,应该用 proxy_pass,而不是 rewrite

last和break#

Terminal window
'默认不加标签和加这俩标签,本质上都是重写,不改变URL'
# 故使用curl命令即可进行测试
# web01中测试即可
[root@web01 ~]#cd /etc/nginx/conf.d/
[root@web01 conf.d]#vim test.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 conf.d]#systemctl restart nginx
[root@web01 conf.d]#vim /etc/hosts
10.0.0.7 test.kpyun.com
[root@web01 conf.d]#curl test.kpyun.com
web01...
[root@web01 conf.d]#curl test.kpyun.com/1.html
bbb
[root@web01 conf.d]#curl test.kpyun.com/2.html
aaa
'目前rewrite就是这么来跳转的,这就是它默认的匹配规则!'
# 如果我们在他后面加上tag后,就可以控制它的匹配
1)测试last标记
[root@web01 conf.d]#vim test.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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.html
aaa
# 访问到1.html跳转到2.html后,停止rewrite,使用新的 URI 重新搜索 `location`
# 所以就匹配到了aaa
2)测试break标记
[root@web01 conf.d]#vim test.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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.html
222
# 后续也不继续搜索 `location`

重定向#

Terminal window
'下面的例子是关于域名的迁移'
HTTP 301 # 永久重定向
HTTP 302 # 临时重定向
✅浏览器地址栏变为新 URL
# 正是因为变成了新的URL,你用curl命令行不通(它会固定URL),得用浏览器
# 浏览器的地址栏会发生变化
2次请求(先访问原URL,再跳转到新URL)

永久重定向(301)#

image-20260301094617369
image-20260301094617369

Terminal window
# 永久的更换域名了,用户只记得老的域名
用户只会在第一次请求源站,当它第二次再访问的时候;
不会请求源站,直接通过缓存请求 `www.oldgirl.com` (新的站点)
1.只要用户访问过一次源站,即使源站挂掉,也不影响客户端访问新的站点
# 因为在浏览器已经缓存下来了
2.浏览器有缓存,但是新站点挂掉了,只有手动清缓存才能访问老站点(缺点)
Terminal window
'permanent-301-永久跳转'
[root@web01 ~]#cd /etc/nginx/conf.d/
[root@web01 conf.d]#vim re.conf
server {
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 -t
systemctl 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,故直接返回状态码301

return跳转#

Terminal window
另一种临时跳转方式:'return'
# 常见格式:返回状态码+新的url地址
[root@web01 conf.d]#vim re.conf
server {
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 -t
systemctl reload nginx

临时重定向(302)#

image-20260301094339874
image-20260301094339874

Terminal window
'每次都会请求源站'
1.如果源站挂掉,则用户无法访问新的站点
2.如果新的站点挂掉,则自动请求源站(优点)
Terminal window
'redirect-302-临时跳转'
[root@web01 conf.d]#vim re.conf
server {
listen 80;
server_name rewrite.kpyun.com;
root /code/re;
location /re {
rewrite ^(.*)$ http://www.baidu.com redirect;
#这次是 空格 redirect
}
}
[root@web01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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 -t
systemctl reload nginx
再次访问 rewrite.kpyun.com/re 依旧跳转到百度页面

跳转案例#

Terminal window
# 我们用域名跳转的比较少,更多的是资源的跳转!
[root@web01 conf.d]#vim re.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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/hosts
10.0.0.7 rewrite.kpyun.com
[root@web01 conf.d]#curl rewrite.kpyun.com/abc/1.html
222...
# 用户访问/abc/1.html实际上真实访问的是/ccc/bbb/2.html
浏览器输入:rewrite.kpyun.com/abc/1.html
'地址栏没有发生变化'

image-20260301115902623
image-20260301115902623

Terminal window
更改一下配置
location /abc/1.html {
return 302 /ccc/bbb/2.html;
}
# 如果你写的是return 302...(临时重定向)
nginx -t
systemctl 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.html
ls: 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
浏览器再次访问
'地址栏改变'

image-20260301120517484
image-20260301120517484

正则表达式匹配#

Terminal window
'参考笔记Nginx02中的location匹配优先级'
1)案例
[root@web01 conf.d]#vim re.conf
server {
listen 80;
server_name rewrite.kpyun.com;
root /code/re;
location ~ /(.*abc)$ {
# 匹配以abc字符结尾的URI
rewrite ^(.*)$ /ccc/bbb/2.html;
# 后面没有加任何标签,普通的跳转,地址栏不变
}
}
nginx -t
systemctl reload nginx
[root@web01 conf.d]#curl rewrite.kpyun.com/no/not_page/hhhabc
222...
# 我的服务器上并没有这些目录和文件,只要是以abc结尾就能够跳转
2)案例
[root@web01 conf.d]#vim re.conf
server {
listen 80;
server_name rewrite.kpyun.com;
root /code/re;
location ~ /2014/ {
rewrite ^/2014/(.*)$ /2026/$1;
}
# 类似于后向引用
# 用户访问/2014/...实际上真实访问的是/2026/...
}
nginx -t
systemctl 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.html
hhhh
# 表面访问的是2014/文件夹下的内容,实际把2014换为了2026,后面的都不变
[root@web01 conf.d]#ll -d /code/re/2014
ls: cannot access '/code/re/2014': No such file or directory
# 实际上就没有2014这个目录
3)案例
[root@web01 conf.d]#vim re.conf
server {
listen 80;
server_name rewrite.kpyun.com;
root /code/re;
location ~ /2014/ {
rewrite ^/2014/(.*)/(.*)$ /2026/$2/$1;
}
# $2和$1他们之间的位置可以发生自由变换
# ^/(.*)/(.*)/(.*)$ 不能这样写!!!前面必须是一个确切的路径
}
nginx -t
systemctl reload nginx
[root@web01 conf.d]#curl rewrite.kpyun.com/2014/bbb/hh.html/ccc
hhhh
[root@web01 conf.d]#cat /code/re/2026/ccc/bbb/hh.html
hhhh

image-20260301152533034
image-20260301152533034

错误页匹配#

Terminal window
4)案例
# 错误页面跳转
'这里可以联想参考Nginx02中的error_page'
# 上面笔记是单个状态码页面进行拦截,下面进行的是整个状态码的拦截!
[root@web01 conf.d]# cat re.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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.com
index
[root@web01 conf.d]#curl rewrite.kpyun.com/ddd/eee
This is a error page
# 访问一个不存在的页面,打印输出...
[root@web01 conf.d]#tail -1 /var/log/nginx/error.log
2026/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.log
10.0.0.7 - - [01/Mar/2026:17:35:49 +0800] "GET /ddd/eee HTTP/1.1" 404 21 "-" "curl/7.71.1" "-"
# 拦截的是404状态码

来源IP地址匹配#

Terminal window
5)案例
# 在请求域名后携带args参数
需求分析:
1.正常用户访问rewrite.kpyun.com,则直接返回首页内容
2.如果是公司内部特定用户访问,则在域名后面加上&showoffline=1
# 假设它的网络IP地址是10.0.0.1
# 至于后面的参数可以理解为开发的需求
当我们访问一个域名的时候默认携带args参数,只不过默认为空;现在开发的需求是让它带上一个特定的参数&showoffline=1
[root@web01 conf.d]# cat re.conf
server {
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=666
echo ${flag}
2)nginx中set写法
set $变量 ;
set $flag 666;
'赋值或者使用都要加上$符号'
-----------------------------
[root@web01 conf.d]#nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@web01 conf.d]#systemctl reload nginx
# 别的IP地址浏览器访问,还是默认页面index
[root@web01 conf.d]#hostname -I
10.0.0.7 172.16.1.7
[root@web01 conf.d]#curl rewrite.kpyun.com
index
浏览器测试访问rewrite.kpyun.com
# IP地址是10.0.0.1
'自动携带参数 &showoffline=1'

image-20260301183415212
image-20260301183415212

Terminal window
6)案例
网站维护,指定IP正常访问,其他IP跳转维护页面
# 公司业务停机维护

image-20260301195600334
image-20260301195600334

Terminal window
[root@web01 conf.d]# cat re.conf
server {
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 -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: 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

image-20260301200625775
image-20260301200625775

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

rewrite跳转
https://www.kpyun.fun/posts/web/nginx/nginx06/
作者
久棹
发布于
2025-11-30
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录