网站首页 > 技术教程 正文
原创 k8svip
写在之前
经常会有人问,nginx rewrite 的事,其实它是很简单的,今天稍微把之前的笔记拿出来分享一下,首先会讲到http请求处理的11个阶段,如果想深入的了解rewrite,就必须对http请求处理的各个阶段有一定的了解,并且如果读nginx源码,也会更加的容易。
(图一)
上图中是nginx处理http请求时,经过的11个阶段,并不是所有的请求都会经过,但大部分都涉及,并且上图中标红的是与rewrite相关的几个阶段;
rewrite 配置说明
语法
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if
rewrite官方解释
If the specified regular expression matches a request URI, URI is changed as specified in the replacement string. The rewrite directives are executed sequentially in order of their appearance in the configuration file. It is possible to terminate further processing of the directives using flags. If a replacement string starts with "http://", "https://", or "$scheme", the processing stops and the redirect is returned to a client.
如果指定的正则表达式匹配一个请求的 URI,则 URI 就按照指定的 replacement 进行重写或重定向,而 rewrite 指令会按照配置文件中出现的顺序执行,并且 flag 标志位可以停止处理;如果 replacement 以"http://"或"https://"或"$scheme"开头,此时停止处理并直接重定向返回客户端;
rewrite语法解释
regex: 对请求的URI做正则匹配,regex匹配的是URI,不包括域名socket和查询参数,默认的查询参数会被追加到replacement末尾,如果不希望在末尾追加query string,可以在replacement的末尾加一个"?";
replacement: 目标URI匹配成功后替换的URL;
flag: 控制指令的执行顺序,如果没有flag,rewrite会根据指令出现的先后顺序,由上到下依次匹配;
rewrite_log指令:,日志文件中会记录rewrite匹配的过程,注意日志是记录在error.log中,可以调试的时候打开 debug 级别查看匹配过程;
flag有哪些
last
stops processing the current set of ngx_http_rewrite_module directives and starts a search for a new location matching the changed URI;
如果匹配的URI,rewrite在server块中,并且last做为flag,匹配到此rewrite URI时,不再向下匹配server块中的rewrite,进而继续下面location URI的查找匹配;
如果匹配的URI,rewrite在location块中,last做为flag,匹配到此rewrite时,会跳出此location块,继续从上到下查找其它的location块URI,但不会再匹配server块中的rewrite中的URI;
break
stops processing the current set of ngx_http_rewrite_module directives as with the break directive;
如果匹配的URI,rewrite在server块中,并且break做为flag,匹配到此rewrite URI时,不再向下匹配server块中的rewrite,进而继续下面location URI的查找匹配;
如果匹配的URI,rewrite在location块中,break做为flag,匹配到此rewrite时,不会跳出此location块,而是继续对location块下面的语句继续运行,不会跳出此location块,并且也不会匹配location 块下面的其它rewrite规则;
完成该rewrite规则的执行后,停止处理后续rewrite指令集,并不再重新查找;但是当前location内剩余非rewrite语句和location外的的非rewrite语句可以执行;
redirect
returns a temporary redirect with the 302 code; used if a replacement string does not start with "http://","https://", 'scheme';(这里的scheme前面有一个¥)
返回302临时重定向,地址栏会显示跳转后的地址;
permanent
returns a permanent redirect with the 301 code.
返回301永久重定向,地址栏会显示跳转后的地址,即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。
rewrite 配置实例
无 flag 测试用例一
server {
listen 80;
rewrite ^/(.*)$ /k8svip_one/$1;
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/abc
测试结果
This is k8svip_two location
uri: /k8svip_two/abc
无 flag 时,rewrite 会依次向下匹配,根据nginx在http请求处理的阶段中,我们会先匹配server块中的rewrite规则;
第一次匹配rewrite ^/(.*)$ /k8svip_one/$1; URI变成:/k8svip_one/abc,无flag继续向下匹配;
第二次匹配rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1; URI变成/k8svip_two/abc;
再向下FIND_CONFIG阶段,查找location进行匹配,正好找到location /k8svip_two/ 所以 response 如上;
无 flag 测试用例二
server {
listen 80;
rewrite ^/(.*)$ /k8svip_one/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1;
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/abc
测试结果:
This is k8svip_two location
uri: /k8svip_two/abc
无flag,处理server块阶段,匹配rewrite ^/(.*)$ /k8svip_one/$1 ,URI为:/k8svip_one/abc;
到FIND_CONFIG阶段,匹配location, location /k8svip_one/ ,这个location块中有rewrite再次匹配^/k8svip_one/(.*)$ /k8svip_two/$1; URI变为:/k8svip_two/abc,这里没有flag,会跳出继续FIND_CONFIG阶段,而不会到 SERVER_REWRITE 阶段;而是匹配location /k8svip_two/ ,所以response如上。
flag redirect 测试用例一
server {
listen 80;
#rewrite ^/(.*)$ /k8svip_one/$1 redirect;
rewrite ^/(.*)$ https://www.baidu.com/ redirect;
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1;
rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
}
测试及结果
测试:浏览器访问 http://127.0.0.1/abc
response:跳转到百度,状态码为302,临时重定向;
这里的flag是redirect,说明需要重定向到replacement, 正好这里的replacement有“https://”,此时会直接跳转并返回给客户端;
如果这里的#rewrite ^/(.*)$ /k8svip_one/$1 redirect; 这里的注释#打开,会出现问题情况呢?使用浏览器测试下,并自行分析下,告诉你结论,会死循环,如果不明白,可以联系我;
flag redirect 测试用例二
server {
listen 80;
server_name a.com;
rewrite_log on;
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1;
rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1 redirect;
rewrite ^/(.*)$ /k8svip_one/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
}
测试及结果
浏览器访问: http://127.0.0.1/k8svip_one/abc
浏览器跳转为:http://127.0.0.1/k8svip_three/abc
浏览器显示结果如下:
This is k8svip_one location
uri: /k8svip_one/k8svip_three/abc
1. 匹配rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1; 后,URI变为:/k8svip_two/abc ; 无flag,继续向下;
2. 继续匹配 rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1 redirect; 302临时重定向,URI: http://127.0.0.1/k8svip_three/abc,
3. 再次访问,此时会从SERVER_REWRITE这个阶段开始,此时匹配的是 rewrite ^/(.*)$ /k8svip_one/$1; URI变为:/k8svip_one/k8svip_three/abc ,无flag,向下FIND_CONFIG阶段;
4. 最后查看location 匹配location /k8svip_one/ ,所以回显如上;
flag permanent 测试用例
1. 这里的用例与redirect是一模一样的,只是状态码不一样,redirect 302 临时重定向, permanent 301 永久重定向,并且两种重定向,浏览器URL都会发现跳转;
2. 301和302重定向时,也有很多人称为外部重定向,这里的意思是他会重新从nginx http请求处理的第一个阶段开始重新匹配,而相对的内部重定向,是指不会到SERVER_REWRITE阶段的重定向,但有可能是REWRITE和FIND_CONFIG这两个阶段的相互跳转查找,在flag break和last的时候会讲解到;
flag last 测试用例一
server {
listen 80;
rewrite_log on;
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1 last;
rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/k8svip_one/abc
测试结果:
This is k8svip_two location
uri: /k8svip_two/abc
1. 匹配 rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1 last;遇到last,停止同级段的匹配,这里的意思是,中止server段向下的匹配,进行FIND_CONFIG阶段,URI变为:/k8svip_two/abc;
这里可以看出,如果last没有中止server段向下的匹配,会匹配rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1,实际结果是没有匹配的;
2. 由上面步骤之后,匹配location /k8svip_two/, 所以会出现上面的response结果;
flag last 测试用例二
server {
listen 80;
server_name a.com;
rewrite_log on;
rewrite ^/(.*)$ /k8svip_one/$1;
rewrite ^/k8svip_three/(.*)$ /k8svip_four/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
rewrite ^/(.*)$ /k8svip_three/$1 last;
rewrite ^/k8svip_three/(.*)$ /;
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
location /k8svip_four/ {
echo "This is k8svip_four location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/abc
测试结果:
This is k8svip_three location
uri: /k8svip_three/k8svip_one/abc
1. 匹配rewrite ^/(.*)$ /k8svip_one/$1; URI变为:/k8svip_one/abc;
2. 匹配location /k8svip_one/ 进而匹配location块中的rewrite ^/(.*)$ /k8svip_three/$1 last; 因为是last,会跳出location继续FIND_CONFIG阶段,
3. URI为:/k8svip_three/k8svip_one/abc;而不会到SERVER_WRITE阶段;
匹配 location /k8svip_three/ ,所以看到上面的response;
flag break 测试用例一
server {
listen 80;
rewrite_log on;
rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1 break;
rewrite ^/k8svip_two/(.*)$ /k8svip_three/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/k8svip_one/abc
测试结果如下:
This is k8svip_two location
uri: /k8svip_two/abc
1. 匹配rewrite ^/k8svip_one/(.*)$ /k8svip_two/$1 break; flag为break结束本层级的rewirte匹配,URI变为:/k8svip_two/abc
2. 继续FIND_CONFIG阶段,匹配location /k8svip_two/ ; 所以response 如上;
flag break 测试用例二
server {
listen 80;
server_name a.com;
rewrite_log on;
rewrite ^/(.*)$ /k8svip_one/$1;
location / {
echo "This is default location";
echo "uri: ${uri}";
}
location /k8svip_one/ {
rewrite ^/(.*)$ /k8svip_three/$1 break;
rewrite ^/k8svip_two/(.*)$ /;
echo "This is k8svip_one location";
echo "uri: ${uri}";
}
location /k8svip_two/ {
echo "This is k8svip_two location";
echo "uri: ${uri}";
}
location /k8svip_three/ {
echo "This is k8svip_three location";
echo "uri: ${uri}";
}
}
测试及结果
测试:curl http://127.0.0.1/abc
测试结果如下:
This is k8svip_one location
uri: /k8svip_three/k8svip_one/abc
1. 匹配rewrite ^/(.*)$ /k8svip_one/$1; URI变为:/k8svip_one/abc
2. 匹配location /k8svip_one/,然后继续 rewrite ^/(.)$ /k8svip_three/$1 break; flag为break,结束本层级的rewrite ^/(.)$ /k8svip_three/$1 break;,并且继续进行本层级的其它操作;
3. 此时的URI:/k8svip_three/k8svip_one/abc,所以response如上;
总结
本文结合理论及实践总结了nginx rewrite规则使用,rewrite可以出现在service段,也可以出现在location 作用域内,它会根据flag标识位的不同做出相应的跳转。
猜你喜欢
- 2024-09-09 「Nginx」Web/代理服务器的瑞士军刀:重写与定位
- 2024-09-09 ingress-nginx常用注解指南(nginx详细讲解)
- 2024-09-09 Nginx反向代理常用配置(nginx反向代理设置)
- 2024-09-09 nginx+springboot使用https重定向的解决办法
- 2024-09-09 Nginx从0基础到进阶实战!运维工程师必看
- 2024-09-09 深度|掌握Nginx监控运维,这一篇足矣!
- 2024-09-09 详解nginx配置location总结及rewrite规则写法
- 2024-09-09 nginx 使用技巧配置(nginx 配置详解)
- 2024-09-09 nginx之Rewrite实战(nginx rewrite_by_lua)
- 2024-09-09 详解 Nginx配置静态内容服务器|附案例说明
你 发表评论:
欢迎- 最近发表
-
- Win11学院:如何在Windows 11上使用WSL安装Ubuntu
- linux移植(Linux移植freemodbus)
- 独家解读:Win10预览版9879为何无法识别硬盘
- 基于Linux系统的本地Yum源搭建与配置(ISO方式、RPM方式)
- Docker镜像瘦身(docker 减小镜像大小)
- 在linux上安装ollama(linux安装locale)
- 渗透测试系统Kali推出Docker镜像(kali linux渗透测试技术详解pdf)
- Linux环境中部署Harbor私有镜像仓库
- linux之间传文件命令之Rsync傻瓜式教程
- 解决ollama在linux中安装或升级时,通过国内镜像缩短安装时长
- 标签列表
-
- 下划线是什么 (87)
- 精美网站 (58)
- qq登录界面 (90)
- nginx 命令 (82)
- nginx .http (73)
- nginx lua (70)
- nginx 重定向 (68)
- Nginx超时 (65)
- nginx 监控 (57)
- odbc (59)
- rar密码破解工具 (62)
- annotation (71)
- 红黑树 (57)
- 智力题 (62)
- php空间申请 (61)
- 按键精灵 注册码 (69)
- 软件测试报告 (59)
- ntcreatefile (64)
- 闪动文字 (56)
- guid (66)
- abap (63)
- mpeg 2 (65)
- column (63)
- dreamweaver教程 (57)
- excel行列转换 (56)
本文暂时没有评论,来添加一个吧(●'◡'●)