nginx rewrite跳转(高级)
官网 https://nginx.org/en/docs/http/ngx_http_rewrite_module.html 该ngx_http_rewrite_module模块用于使用 PCRE 正则表达式更改请求 URI、返回重定向和条件选择配置。
1.介绍
实际工作需求中,我们经常要修改用户url的请求
比如早期的京东官网,域名叫做
360buy.com
企业就进行域名修改。
jd.com
老用户他又不知道你改名了,
360buy.com 看到网页无响应,以为京东挂了。。不用这个网站了,京东跑路了,以后用拼多多吧。。
京东就是用rewrite技术,实现,让旧域名的请求,自动重定向(永久重定向)到新域名
老客户浏览器发出请求 www.360buy.com 浏览器自动的又发出一个新请求,跳转到新请求域名上 www.jd.com(会发现浏览器的url,也自动更换为了新的域名)
1.例如客户端默认发送是http协议,我们的网站都支持了https部署,需要将用户的http请求强制跳转到https。 2.网站自适应移动端、或者PC端,将用户请求自动跳转到移动端服务器、或者PC端服务器 例如 http://yuchaoit.cn PC端 http://m.yuchaoit.cn 3.这个功能就得通过ngx_http_rewrite_module 这个模块实现 该模块提供了多个指令功能 break # 中断配置 if # 请求判断 set # 设置变量 return # 返回值 rewrite # 对用户请求URL重写
2.指令语法(if)
1.if语句,用于条件判断,根据判断结果的不同,执行不同的动作,if写在server{}或者location{}标签里。 if (匹配条件) { 执行动作 }
2.1 匹配规则
1.if语句,用于条件判断,根据判断结果的不同,执行不同的动作,if写在server{}或者location{}标签里。
# 比如针对用户的请求客户端判断,或者针对用户的ip地址判断
# 基于nginx的内置变量就可以提取出这些信息。。
if (匹配条件) {
执行动作
}匹配条件
- nginx内置变量
- 使用nginx的if提供的条件判断符号,等于不等于,....
条件符号
符号 | 作用 |
---|---|
= | 比较变量、字符串是否相等,相等为true、不等则为false |
!= | 比较变量、字符串是否不相等,不相等为true、相等为false |
~ | 区分大小写的正则匹配,匹配上为true,否则为false |
!~ | 区分大小写的正则匹配,不匹配上为true,否则为false |
~* | 不区分大小写的正则匹配,匹配上为true,否则为false |
!~* | 不区分大小写的正则匹配,不匹配上为true,否则为false |
条件参数
符号 | 作用 |
---|---|
-f 和 !-f | 请求的文件是否存在 |
-d 和 !-d | 判断的目录是否存在 |
-e 和 !-e | 判断的文件、目录、软连接是否存在 |
-x 和 !-x | 判断的请求文件是否有有执行权限 |
2.2 创建测试配置文件(if)
针对不同的情况进行判断,动作设置。
server { # 客户端完全匹配到 listen 22555; server_name localhost; root html; charset utf-8; location /test-if { # 客户端类型完全匹配到 huawei if ($http_user_agent = huawei){ echo "agent is huawei"; } # 客户端类型区分大小写 if ($http_user_agent ~ Iphone) { echo "agent is Iphone"; } # 客户端类型不区分大小写 if ($http_user_agent ~* Chrome) { echo "agent is Chrome"; } # 如果请求方法不是GET就提示 ”只能用GET方法,你这个烂玩家“ if ($request_method != GET) { echo "必须是GET方法,你这个烂玩家"; } # 如果是IE浏览器,直接提示 "不支持IE,请下载Chrome浏览器" # 不区分大小写的正则匹配 if ($http_user_agent ~* IE){ echo "不支持IE,请下载Chrome浏览器"; } # 如果上面没有任何匹配,执行如下语句 echo "if规则没有匹配到"; echo "agent is >>>>>> $http_user_agent"; echo "request_method is >>>>>>>> $request_method"; } }
2.3 测试访问
默认访问,没有匹配到if规则
[root@master-61 ~]#curl 10.0.0.9:22555/test-if if规则没有匹配到 agent is >>>>>> curl/7.29.0 request_method is >>>>>>>> GET [root@master-61 ~]#
测试完全匹配
[root@master-61 ~]#curl -A 'huawei' 10.0.0.9:22555/test-if agent is huawei [root@master-61 ~]# [root@master-61 ~]#curl -A 'huaweiiiii' 10.0.0.9:22555/test-if if规则没有匹配到 agent is >>>>>> huaweiiiii request_method is >>>>>>>> GET
测试区分大小写的正则匹配
[root@master-61 ~]#curl -A 'Iphone' 10.0.0.9:22555/test-if agent is Iphone [root@master-61 ~]# [root@master-61 ~]#curl -A 'iphone' 10.0.0.9:22555/test-if if规则没有匹配到 agent is >>>>>> iphone request_method is >>>>>>>> GET [root@master-61 ~]#curl -A 'aaaaaiphone' 10.0.0.9:22555/test-if if规则没有匹配到 agent is >>>>>> aaaaaiphone request_method is >>>>>>>> GET [root@master-61 ~]#curl -A 'aaaaaIphone' 10.0.0.9:22555/test-if agent is Iphone [root@master-61 ~]#curl -A 'aaaaaIphonebbbbbb' 10.0.0.9:22555/test-if agent is Iphone
测试不区分大小写的正则匹配
[root@master-61 ~]#curl -A 'Chrome' 10.0.0.9:22555/test-if agent is Chrome [root@master-61 ~]# [root@master-61 ~]# [root@master-61 ~]#curl -A 'chrome' 10.0.0.9:22555/test-if agent is Chrome [root@master-61 ~]#curl -A 'aaaaaaaChrome' 10.0.0.9:22555/test-if agent is Chrome [root@master-61 ~]#curl -A 'BBBBBbaaaaaaaChrome' 10.0.0.9:22555/test-if agent is Chrome [root@master-61 ~]#curl -A 'BBBBBbaaaaaaaChromeCCCC' 10.0.0.9:22555/test-if agent is Chrome [root@master-61 ~]#curl -A 'BBBBBbaaaaaaaChrComeCCCC' 10.0.0.9:22555/test-if if规则没有匹配到 agent is >>>>>> BBBBBbaaaaaaaChrComeCCCC request_method is >>>>>>>> GET
测试请求方法POST
curl默认就是GET方法 curl -X method --data '数据' [root@master-61 ~]#curl -X POST --data '{"name":"chaoge01"}' 10.0.0.9:22555/test-if 必须是GET方法,你这个烂玩家
测试浏览器、分别用IE浏览器、Chrome测试。
3.指令(return)
https://nginx.org/en/docs/stream/ngx_stream_return_module.html The ngx_stream_return_module module (1.11.2) allows sending a specified value to the client and then closing the connection. Example Configuration server { listen 12345; return $time_iso8601; } Syntax: return value; Default: — Context: server Specifies a value to send to the client. The value can contain text, variables, and their combination. 指定要发送到客户端的值。 该值可以包含文本、变量及其组合。 指令说明 return用于返回如状态码 或者重写url 或者响应状态码、以及文本等 return之后的命令不会再执行。
3.1 return用法
return 可以用于 server {} ; location {} ; if {}; return code [text]; return code url; return url;
3.2 配置文件
[root@web-9 /etc/nginx/conf.d]#cat return.conf server { listen 22666; server_name _; root html; # 精确匹配,客户端只访问了网页根目录 location = / { echo "welcome to chaoge linux course."; } location /test-return { # 客户端完全匹配 if ($http_user_agent = huawei){ return 200 "agent is $http_user_agent \n"; } # 限制必须是GET方法 if ($request_method != GET){ return 405 "必须是GET方法!其他方法不允许\n"; } # 如果是IE浏览器,就重定向 if ($http_user_agent ~* IE){ return 301 http://yuchaoit.cn/cai.jpg; } # 没有if条件匹配到 return 404 "sorry, nothing ....\n"; } # 默认匹配,如果没有匹配到任意内容,跳转到首页 jd.com就是这个做法 location / { return 301 http://yuchaoit.cn/cai.jpg; } location /ji { return 500 "鸡你太美\n"; } }
3.3 测试访问
精确匹配访问
随便输入url,访问错误的内容
10.0.0.9:22666/qweqweqweqweqwe 默认会跳转301,页面重定向
设置访问客户端
[root@master-61 ~]#curl 10.0.0.9:22666/test-return sorry, nothing .... 精确完全匹配 [root@master-61 ~]#curl -A 'huawei' 10.0.0.9:22666/test-return agent is huawei [root@master-61 ~]# [root@master-61 ~]# [root@master-61 ~]#curl -A 'aaahuawei' 10.0.0.9:22666/test-return sorry, nothing .... 不允许POST方法 [root@master-61 ~]#curl -X POST 10.0.0.9:22666/test-return 必须是GET方法!其他方法不允许 测试用ie浏览器访问 10.0.0.9:22666/test-return 请求都会被重定向 测试访问/ji 路径,返回500状态码,以及字符串 [root@master-61 ~]#curl 10.0.0.9:22666/ji -I HTTP/1.1 500 Internal Server Error Server: nginx/1.19.0 Date: Tue, 10 May 2022 07:57:42 GMT Content-Type: application/octet-stream Content-Length: 13 Connection: keep-alive [root@master-61 ~]# [root@master-61 ~]#curl 10.0.0.9:22666/ji 鸡你太美
测试关于ie浏览器的封禁,很多企业开发的网站,以及是不再支持ie浏览器了
你可能还会有很老旧的用户,用的机器是ie,会导致网站一些资源无法加载
是你网站的问题。。
运维需要针对用户客户端判断,发现是ie,就告诉他ie不被支持,直接重定向
4.set指令
1.语法
set就是用于设置一个nginx变量,这个值可以是文本、变量或者其组合。 set可以用于设置server{} location{} if{} set 变量名 变量值;
2.配置文件
server { listen 22777; server_name _; root html; set $my_url http://yuchaoit.cn/cai.jpg; location /test-set { return 301 $my_url; } }
3.测试访问
浏览器访问10.0.0.9:22777/test-set 会自动被重定向
5.指令(break)
break是专门用于终止,rewrite的其他指令的执行的
rewrite这个url重写模块,支持如下几个关键字
break, if, return, rewrite, and set
这些关键字都可以在server{} location中定义
break的作用是,nginx的代码,执行带break之后,就会停止后续的
if, return, rewrite, set指令的执行。。
结合rewrite实际用法,来看break的其他用法
1.语法
break用于终止所在区域的后续指令,且只针对ngx_http_rewrite_module提供的模块指令; 也就是咱们目前所学的这几个rewrite相关的指令,在break后面不会执行了。 break可以用于 server{} location{} if{}
2.配置文件
server { listen 22888; server_name _; root html; location / { set $my_website yuchaoit.cn; echo "welcome to my website:" $my_website; break; set $my_name yuchao; echo "my name is" $my_name; } }
3.执行结果
[root@master-61 ~]#curl 10.0.0.9:22888 welcome to my website: yuchaoit.cn my name is 发现break后续的 set指令并未正确执行。
6.rewrite指令(工作必需品)
你上面学 if,return,set,break都是为了这个指令去服务的 当你去访问 实际的京东的官网,是怎么用rewrite技术的 # ?key=value 这是基于get请求格式的,url传递参数 # 用于交给后端编程语言,提取这个key,value的 1. https://www.360buy.com/index.html?name=yuchao 301跳转永久重定向 (信息1: 访问的主机,端口,以及后续的url, 后续的参数index.html?name=yuchao) 2. 当发生301跳转之后,会保留后续的所有url,后续的路径参数,全部转发给新的域名 知道了 旧 www.360buy.com 新域名 www.jd.com 除了要让域名跳转之外,还得实现,参数的保留!!!!最重要的 京东的做法是,跳转到 www.jd.com且保留了参数 http://www.jd.com/index.html?name=yuchao rewrtite重写技术且保留的参数
实现这个用法
句法: rewrite regex replacement [flag];
默认: —
语境: server, location,if
rewrite 目的就是为了提取出url后面的参数 新的域名 [参数,301永久跳转,302临时跳转]
官网 https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite
6.1 指令语法
1. rewrite指令可以基于用户的请求url,再通过正则表达式的匹配情况,进行地址重写; 2. rewrite指令可以写多条,按照顺序依次执行; 3. rewrite指令可以根据flag标记进行进一步处理(last、break、redirect、permanent)
6.2 flag参数解释
句法: rewrite regex replacement [flag];
默认: —
语境: server, location,if
可选flag参数可以是以下之一: last 停止处理当前的 ngx_http_rewrite_module指令集,向下匹配新的locaiton URI规则; break ngx_http_rewrite_module与break指令一样, 停止处理当前的指令集 ; redirect(公司的域名临时更换) 返回带有 302 代码的临时重定向; 如果替换字符串不以“ http://”、“ https://”或“ $scheme”开头,则使用该字符串; 浏览器将显示跳转后的url地址,且浏览器不会做dns缓存记录; permanent(公司域名永久更换,老域名还在运行) 返回带有 301 代码的永久重定向。 浏览器会记录跳转后的dns缓存,浏览器显示跳转后的url。
6.3工作应用场景
1.设置redirect、permanent参数,浏览器都会更改为跳转后的url,是由服务器返回新的URL,客户端对这个URL重新发起了请求。 2.设置last和break参数,浏览器依然显示原本的URL,由于服务器内部完成跳转。 3.last和break区别 last在标记完本次规则匹配完成后,对其所在的server{}标签重新发起修改后的URL请求,再次匹配location{}。 break是在本条规则匹配完毕后,终止匹配,不再匹配后面的location{};
6.4 redirect和permanent实战
permanent和301永久重定向
HTTP协议规范里,301是永久重定向、302是临时重定向。 工作场景 公司的旧域名需要永久跳转到新域名。 www.pythonav.cn ↓ www.yuchaoit.cn 状态码为301.
旧网站配置文件
# 0.注意要做好本地dns解析 10.0.0.9 www.pythonav.cn www.yuchaoit.cn # 1.创建测试数据 mkdir -p /pythonav echo "i am pythonav " > /pythonav/index.html # 2.配置文件 cat /etc/nginx/conf.d/pythonav.conf server { listen 80; server_name www.pythonav.cn; location / { root /pythonav/; index index.html; rewrite / http://www.yuchaoit.cn permanent; } } # 3.重启 systemctl restart nginx
新网站配置文件
# 0.注意要做好本地dns解析 10.0.0.9 www.pythonav.cn www.yuchaoit.cn # 1.创建测试数据 mkdir -p /www.yuchaoit.cn/ echo 'i am www.yuchaoit.cn' > /www.yuchaoit.cn/index.html # 2.配置文件 [root@web-9 /etc/nginx/conf.d]#cat www.yuchaoit.cn.conf server { listen 80; server_name www.yuchaoit.cn; location / { root /www.yuchaoit.cn/; index index.html; } } 3.重启 systemctl restart nginx
测试访问
做好dns解析 10.0.0.9 www.pythonav.cn www.yuchaoit.cn 1.并且你会发现浏览器中提示的是 disk cache,表示这个域名做了dns缓存 2.新域名的请求提示是304,表示请求正确,但是这个文件没有任何变化
公司的旧网站 www.pythonav.cn依然提供访问,但是用户访问后,自动跳转到了新网站 www.yuchaoit.cn 且浏览器状态码是301,显示永久重定向,就是这个旧网站已经被弃用了,自动跳转了新的。 使用场景又比如 1. 用户输入 非www的网址(yuchaoit.cn),自动重定向到www.yuchaoit.cn 2. http跳转https 3. 域名更换
6.5 redrict 302临时跳转
302临时跳转,用于因为某些原因,域名要临时跳转,旧的网站url还是会继续使用的,例如公司搞了一个活动页面等,活动结束后要取消这个跳转。
302临时跳转需求
用户访问www.yuchaoit.cn 需要临时跳转到party.yuchaoit.cn
旧配置文件
[root@web-9 /etc/nginx/conf.d]#cat www.yuchaoit.cn.conf server { listen 80; server_name www.yuchaoit.cn; location / { root /www.yuchaoit.cn/; index index.html; rewrite / http://party.yuchaoit.cn redirect; } }
新配置文件
# 1.创建测试数据 mkdir -p /party.yuchaoit.cn/ echo 'i am party.yuchaoit.cn' > /party.yuchaoit.cn/index.html # 2.配置文件 server { listen 80; server_name party.yuchaoit.cn; location / { root /party.yuchaoit.cn/; index index.html; } } # 3.重启服务 systemctl restart nginx
客户端测试302跳转
1.做好dns解析
10.0.0.9 www.pythonav.cn www.yuchaoit.cn party.yuchaoit.cn
2.浏览器测试
发生了302跳转,表示临时重定向
并且没有看到disk cache,表示并未做dns缓存
6.6 break和last实践
last实验
再来看语法
2.设置last和break参数,浏览器依然显示原本的URL,由于服务器内部完成跳转。
3.last和break区别
last在标记完本次规则匹配完成后,对其所在的server{}标签重新发起修改后的URL请求,再次匹配location{}。
break是在本条规则匹配完毕后,终止匹配,不再匹配后面的location{};
测试需求
可以从 location {} > location {} > location {}
多次匹配。
访问AAA、重写到BBB、重写到CCC,且是服务器内部跳转。
配置文件
- 访问AAA
- 服务器内部跳转BBB
- 最后跳转到CCC
# 创建测试数据,用于查看url内部跳转效果,以及保持了url的参数 # 1.创建测试数据 mkdir -p /www/ echo 'i am ccc, how are you ~~~' > /www/hello.html # 2.配置文件 server { listen 30000; server_name _; # location /CCC { alias /www/; } location /BBB { rewrite ^/BBB/(.*)$ /CCC/$1 last; } location /AAA { rewrite ^/AAA/(.*)$ /BBB/$1 last; } }
第一次跳转
第二次跳转
last测试
访问以/AAA/路径开头的url即可
[root@master-61 ~]#curl 10.0.0.9:30000/AAA/hello.html i am ccc, how are you ~~~ [root@master-61 ~]#curl 10.0.0.9:30000/BBB/hello.html i am ccc, how are you ~~~ [root@master-61 ~]# [root@master-61 ~]#curl 10.0.0.9:30000/CCC/hello.html i am ccc, how are you ~~~ [root@master-61 ~]# [root@master-61 ~]#curl 10.0.0.9:30000/DDD/hello.html <html> <head><title>404 Not Found</title></head> <body> <center><h1>404 Not Found</h1></center> <hr><center>nginx/1.19.0</center> </body> </html>
可以证明last会向下匹配。
break实验
break是在本条规则匹配完毕后,终止匹配,不再匹配后面的location{};
表示中断匹配,访问到AAA资源后,只rewrite跳转一次,终止后续的跳转。
# 创建测试数据,用于查看url内部跳转效果,以及保持了url的参数
# 2.配置文件
server { listen 31000; server_name _; # location /CCC { root /www/; index index.html; } location /BBB { root /www/; index index.html; rewrite ^/BBB/(.*)$ /CCC/$1 last; } location /AAA { root /www/; index index.html; rewrite ^/AAA/(.*)$ /BBB/$1 break; } }
注意点,这里的配置文件使用的是root参数
root参数设置的规则是,去root定义的目录下,寻找对应的该目录。
因此得在/www目录下,创建对应的文件夹
mkdir -p /www/{AAA,BBB,CCC} echo 'AAA' > /www/AAA/index.html echo 'BBB' > /www/BBB/index.html echo 'CCC' > /www/CCC/index.html
测试访问
访问AAA路径
[root@web-9 /etc/nginx/conf.d]#curl 10.0.0.9:31000/AAA/index.html BBB
6.7 生产rewrite实践(一)
公司的博客url连接,旧的如下
www.yuchaoit.cn/blog
现在业务变更,需要添加三级域名为 blog.yuchaoit.cn,需要将www.yuchaoit.cn/blog这个url的请求,转发给blog.yuchaoit.cn
例如
http://www.yuchaoit.cn/blog/login
http://www.yuchaoit.cn/blog/hello-world
都会跳转到
http://blog.yuchaoit.cn/login
http://blog.yuchaoit.cn/hello-world.html
配置文件(www官网配置)
# 1.配置文件 server { listen 80; server_name www.yuchaoit.cn; charset utf-8; location / { root /www/; index index.html; } # 针对旧域名进行url重写 # 匹配/blog/路径,然后rewrite location /blog/ { # 使用正则表达式,提取url参数 rewrite ^/blog/(.*)$ http://blog.yuchaoit.cn/$1 redirect; } } # 2.测试数据 echo 'hello ,i am www 官网 ~~~~~~~' > /www/index.html # 3.重启服务 systemctl restart nginx
配置文件(blog业务配置)
# 1.配置文件 # 1.配置文件 server { listen 80; server_name blog.yuchaoit.cn; charset utf-8; location / { root /blog/; index index.html; } } # 2.创建测试数据 mkdir -p /blog echo 'hello ,i am blog 博客 ~~~~~~~' > /blog/index.html # 3.重启服务 systemctl restart nginx
测试访问
1.做好dns解析 10.0.0.9 www.pythonav.cn www.yuchaoit.cn blog.yuchaoit.cn
默认页面,location匹配返回官网页面。
访问blog路径
http://www.yuchaoit.cn/blog/index.html 查看是否会跳转
6.8 生产rewrite实践(二)
用户访问
http://www.yuchaoit.cn:80
但是现在该网站添加了支付功能,为了保证http数据传输安全,添加上https证书对数据加密,
因此必须改为访问
https://www.yuchaoit.cn:443
但是你又不能强制性要求用户每次都访问
https://xxxxx
所以你服务端必须做好跳转。
1.创建证书
1.网站的证书应该是由权威企业颁发,这样浏览器才能信任,自建的证书,只是在内网环境下使用。 mkdir /etc/nginx/ssl_key cd /etc/nginx/ssl_key # 输入2次密码 chaoge666 # openssl创建私钥文件 server.key,基于rsa算法,生成的 私钥长度是2048 openssl genrsa -idea -out server.key 2048 # 自己颁发证书,crt是证书的后缀名称,以及设置证书的有效期是100年,以及证书的算法等 # 然后填入证书对应的网站信息,如国家,公司名,邮箱等 [root@web-9 /etc/nginx/ssl_key]#openssl req -days 36500 -x509 -sha256 -nodes -newkey rsa:2048 -keyout server.key -out server.crt Generating a 2048 bit RSA private key ..........................................................+++ ................+++ writing new private key to 'server.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]:CN State or Province Name (full name) []:BJ Locality Name (eg, city) [Default City]:BJ Organization Name (eg, company) [Default Company Ltd]:yuchaoit Organizational Unit Name (eg, section) []:yuchaoit Common Name (eg, your name or your server's hostname) []:yuchaoit Email Address []:[email protected] 3. 确认生成了证书文件 [root@web-9 /etc/nginx/ssl_key]#ll -h total 8.0K -rw-r--r-- 1 root root 1.4K May 10 20:24 server.crt -rw-r--r-- 1 root root 1.7K May 10 20:24 server.key 此时自建的一个证书就可以使用了
2.nginx配置文件支持https
# 配置文件 [root@web-9 /etc/nginx/ssl_key]#cat /etc/nginx/conf.d/ssl.conf server { listen 443 ssl; server_name www.yuchaoit.cn; ssl_certificate /etc/nginx/ssl_key/server.crt; ssl_certificate_key /etc/nginx/ssl_key/server.key; charset utf-8; location / { root /www; index index.html; } } # 创建测试数据 [root@web-9 /etc/nginx/ssl_key]#cat /www/index.html hello ,i am www 官网 ~~~~~~~
3.重启nginx,访问https
http://www.yuchaoit.cn/
https://www.yuchaoit.cn/
点击高级继续访问
此时网站已经是支持https的了,但是浏览器并不信任,因此你需要去阿里云购买一个公网信任的证书即可。
4.配置https自动跳转
配置默认的80官网,跳转到https即可。
[root@web-9 /etc/nginx/conf.d]#cat www.conf server { listen 80; server_name www.yuchaoit.cn; charset utf-8; rewrite ^(.*) https://$server_name$1 redirect; }
5.打开无痕浏览器,查看访问
6.9 开启nginxrewrite重写日志功能
能很清晰帮帮主你调试rewrite的结果,非常好用。
error_log /data/log/nginx/error.log notice; rewrite_log on;
标签:www,cn,rewrite,实践,server,nginx,跳转,yuchaoit,root From: https://www.cnblogs.com/sxy-blog/p/17463358.html