概述
背景
这一章我们来一起聊聊Nginx的Rewrite的功能,Rewrite用于对请求的URL进行重写,然后返回重定向或有条件地选择配置上。后续我们需要了解的Nginx的HTTPS的功能也是基于Rewrite之上的。接下来我们展开说说吧。
Rewrite详解
1. 什么是Rewrite?
Rewrite主要实现URL地址的重写,以及URL地址的跳转;即:就是将用户请求web服务器的URL地址重新修改为其他URL地址的过程。
2. Rewrite的应用场景
2.1 地址跳转:比如当用户访问的xhz.com/edu这个URL时,将其重定向到一个新的域名edu.xhz.com。
2.2 协议跳转:当用户通过http的请求协议重新跳转至https协议(实现https的主要手段)。
2.3 URL静态化:将动态URL地址显示为静态URL的一种技术,能提高搜索引擎的抓取,并能减少动态URL对外暴露过多的参数。(Rewrite会轻微增加服务器的负担)。
3. 如何实现?
通过ngx_http_rewrite_module模块支持url重写、支持if条件判断,但不支持else。另外该模块需要PCRE支持,应在编译nginx时指定PCRE支持。根据相关变量重定向和选择不同的配置,从一个location跳转到另一个location,不过这样的循环最多可以执行10次,超过后nginx将返回500错误。同时,重写模块包含set指令,来创建新的变量并设其值,如记录条件标识、传递参数到其他location、记录做了什么等等。
ngx_http_rewrite_module官网:https://nginx.org/en/docs/http/ngx_http_rewrite_module.html
4. Rewrite参数
4.1 break
只执行break所在的指令,停止执行break后续的所有指令。
### 语法
Syntax: break;
Default: —
Context: server, location, if
### 示例
if ($slow) {
limit_rate 10k;
break;
}
4.2 if
对给定的条件(condition)进行判断,如果条件为真,大括号内的rewrite指令将被执行。
Syntax: if (condition) { ... }
Default: —
Context: server, location
condition条件可以满足如下:
***当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false;
1. 使用“=”和“!=”比较一个变量和字符串;
2. 使用“~”做正则表达式匹配,“~*”做不区分大小写的正则匹配,“!~”做区分大小写的正则不匹配;
3. 使用“-f”和“!-f” 检查一个文件是否存在;
4. 使用“-d”和“!-d”检查一个目录是否存在;
5. 使用“-e”和“!-e”检查一个文件、目录、符号链接是否存在;
6. 使用“-x”和“ !-x”检查一个文件是否可执行;
示例:
// 当请求头中的User-Agent中包含MSIE(~区分大小写)时rewrite请求到/msie/$1目录下,$1表示匹配的URI
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
// 当请求头中的cookie匹配正则的时候,将设置变量$id 为$1 其中$1= =([^;]+)(?:;|$)匹配到的内容
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
set $id $1;
}
// 当请求头中的请求类型method是POST的时,直接返回405
if ($request_method = POST) {
return 405;
}
//如果$slow可以通过set指令设置,则进行限速处理
if ($slow) {
limit_rate 10k;
}
// 如果为真,则返回403
if ($invalid_referer) {
return 403;
}
//如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
}
//如果请求头中包含"post=140",则重定向到example.com
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
}
上诉示例来自nginx的官网,可以发现在匹配的过程中主要还是正则表达式,在来回顾下正则。
= 精准匹配
^~ 以某个字符串开头
~ 区分大小写的正则匹配
/ 通用匹配,任何请求都会匹配到
~* 不区分大小写的正则匹配
. :匹配除换行符以外的任意字符
? :重复0次或1次
+ :重复1次或更多次
* :重复0次或更多次
d :匹配数字
^ :匹配字符串的开始字符
$ :匹配字符串的结束字符
{n} :重复n次
{n,} :重复n次或更多次
[c] :匹配单个字符c
[a-z] :匹配a-z小写字母的任意一个
4.3 return
停止处理并为客户端返回状态码,非标准的444状态码将关闭连接,不发送任何响应头。可以使用的状态码有:204,400,402-406,408,410, 411, 413, 416与500-504。如果状态码附带文字段落,该文本将被放置在响应主体。相反,如果状态码后面是一个URL,该URL将成为location头部值。没有状态码的URL将被视为一个302状态码。此外,可以将带有代码 302 的临时重定向 URL 指定为唯一参数。此类参数应以“http://”、“https://”或“$scheme”字符串开头。 URL 可以包含变量。
Syntax: return code [text];
return code URL;
return URL;
Default: —
Context: server, location, if
4.4 rewrite
如果指定的正则表达式与请求 URI 匹配,则 URI 将按照替换字符串中的指定进行更改。重写指令按照它们在配置文件中出现的顺序依次执行。可以使用标志终止对指令的进一步处理。如果替换字符串以“http://”、“https://”或“$scheme”开头,则处理停止并将重定向返回给客户端。
Syntax: rewrite regex replacement [flag];
Default: —
Context: server, location, if
regex : 正则表达
replacement : 重定向的内容
[flag]: 标志位,包含:last,break,redirect,permanent
regex和replacement没什么具体可说的,后续我们通过示例进行理解就行,主要是flag的参数是什么含义,我们需要了解下。我们先看个示例吧!
//当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为b.html中的内容。
server {
listen 80;
server_name xhz_rewrite.com www.xhz_rewrite.com;
root /rewrite;
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;
}
}
//当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为2.html中的内容。
server {
listen 80;
server_name xhz_rewrite.com www.xhz_rewrite.com;
root /rewrite;
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;
}
}
//当通过www.xhz_rewrite.com/1.html访问时,此时通过rewrite返回的结果为a.html中的内容。
server {
listen 80;
server_name xhz_rewrite.com www.xhz_rewrite.com;
root /rewrite;
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;
}
}
总结:
break:完成该rewrite规则的执行后遇到break就会终止后所有指令的执行。
last:完成该rewrite规则的执行后遇到last,就会将重写后的URI,重server开头开始匹配,匹配到哪个就执行哪个。
//通过 www.xhz_rewrite.com/1.html访问,放回的结果是3.htnl的内容,返回的转态码为301
server {
listen 80;
server_name xhz_rewrite.com www.xhz_rewrite.com;
root /rewrite;
location / {
rewrite /1.html /2.html permanent;
rewrite /2.html /3.html;
}
}
//通过 www.xhz_rewrite.com/1.html访问,放回的结果是3.htnl的内容,返回的转态码为302
server {
listen 80;
server_name xhz_rewrite.com www.xhz_rewrite.com;
root /rewrite;
location / {
rewrite /1.html /2.html redirect;
rewrite /2.html /3.html;
}
}
总结:
redirect:返回302临时重定向,地址栏会显示跳转后的地址;
permanent:返回301永久重定向,地址栏会显示跳转后的地址;即表示如果客户端不清理浏览器缓存,那么返回的结果将永久保存在客户端浏览器中了。因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return
Rewrite实例
1. 根据浏览器的语言不同调度到不同的页面中。
server {
listen 80;
server_name xhz_chinese.com www.xhz_chinese.com;
root /rewrite;
location / {
if ($http_accept_language ~* "zh-CN|zh") {
set $language zh;
}
if ($http_accept_language ~* "en") {
set $language en;
}
rewrite ^/$ /$language;
}
}
2. 通过手机访问xhz.iphone.com跳转到xhz.iphone.com/test
server {
listen 80;
server_name xhz_iphone.com www.xhz_iphone.com;
root /rewrite/iphone;
location / {
if ($http_user_agent ~* "iphone|android|ipad") {
rewrite ^/$ /test;
}
}
}
3. 通过收集手机xhz.test.com跳转到edu.xhz.test.com
server {
listen 80;
server_name xhz123.com www.xhz123.com;
root /rewrite/xhz123;
location / {
index index.html;
if ($http_user_agent ~* "iphone|android|ipad") {
rewrite ^/$ http://edu_xhz_iphone.com;
}
}
}
4. 通过http协议请求,自动跳转到https协议。
server {
listen 80;
server_name xhz_https.com www.xhz_https.com;
root /rewrite/https;
location ^(.*)$ {
rewrite ^(.*)$ https://$server_name$1 redirect;
}
}
server {
listen 443 default;
server_name xhz_https.com www.xhz_https.com;
}
5. 网站维护过程中,希望用户访问所有网站都重定向到一个维护页面。
server {
listen 80;
server_name xhz_wh.com www.xhz_wh.com;
root /rewrite/wh;
rewrite ^(.*)$ /wh.html break;
location / {
index index.html;
}
}
6. 单服务器遇到403 404 502等错误时,自动跳转到临时维护的静态页面。
server {
listen 80;
server_name xhz_static.com www.xhz_static.com;
root /rewrite/static;
location / {
index index.html;
}
error_page 404 403 502 = @err_html
location @err_html {
rewrite ^(.*)$ /static.html break;
}
}
7. 公司网站在停机维护时,指定ip能正常访问,其他ip跳转到维护页面。
server {
listen 80;
server_name bind_ip.com www.bind_ip.com;
root /rewrite/bind_ip;
set $ip 0;
if ($remote_addr = '192.168.65.2|192.168.65.3') {
set $ip 1;
}
if ($ip = '0') {
rewrite ^(.*)$ /bind_ip.html break;
}
## 如果想针对耨个location进行操作,则将如上配置写入location中即可
location / {
index index.html;
}
}
8. 公司网站后台/admin,只允许公司的出口公网ip可以访问,其他ip访问全部返回500
server {
listen 80;
server_name admin.com www.admin.com;
root /rewrite/;
location /admin {
set $ip 0;
if ($remote_addr = ' 113.57.152.160| 113.57.152.161') {
set $ip 1;
}
if ($ip = '0') {
return 500;
}
index index.html;
}
}
最后
以上就是单薄保温杯为你收集整理的Nginx的Rewrite详解(七)背景 Rewrite详解Rewrite实例的全部内容,希望文章能够帮你解决Nginx的Rewrite详解(七)背景 Rewrite详解Rewrite实例所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复