Nginx rewrite
一、什么是Nginx rewrite
Nginx rewrite
主要功能是实现URL地址重写。Nginx的 rewrite 规则需要PCRE软件的支持,即通过Perl兼容正则表达式语法进行规则匹配
二、Nginx rewrite 语法和参数介绍
1、Nginx rewrite 语法
rewrite regex replacement
[flag];
rewrite:固定格式
regex: 正则表达式
replacement:重写后的URL
flag: 重写状态标记
可以应用的位置:
server ,location , if
rewrite ^/(.*) http://www.renxiaoyu.com/$1permanent; #四种颜色分别是上述的语法格式
2、正则表达式和flag参数
字符 |
描述 |
\ |
将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。列入, "\n" 匹配一个换行符,序列"\\"和"\$"则匹配"$" |
^ |
匹配输入字符串的起始位置,如果设置了RegExp对象的Multiline属性,^也匹配"\n" 或"\r"之前的位置 |
$ |
匹配输入字符串的结束位置,如果设置了RegExp对象的Multiline属性,$也匹配"\n" 或"\r"之前的位置 |
* |
匹配前面的字符零次或多次,例如,ol*能匹配"o"及"olll",*等价于{0,} |
+ |
匹配前面的字符一次或多次,例如,"ol+"可以匹配"ol"或"oll",但不能匹配"o", .+等价于{1,} |
? |
匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do” ?等价于{0,1}。 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时, |
. |
匹配除“\r\n”之外的任何单个字符。要匹配包括“\r\n”在内的任何字符, 请使用像“[\s\S]”的模式。 |
(pattern) |
匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合 得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9 属性。要匹配圆括号字符,请使用“\(”或“\)”。 |
flag标记符号 |
说明 |
last |
本条规则匹配完成后,继续向下匹配新的location URL规则 |
break |
本条规则匹配完成即终止,不再匹配后面的任何规则 |
redirect |
返回302临时重定向,浏览器地址栏会显示条状后的URL地址 |
permanent |
返回301永久重定向,浏览器地址栏会显示条状后的URL地址 |
三、案例练习
1、实现域名的重定向
环境:现有公司官网域名,bbs.proxy.com,由于其他原因现需要将域名解析到新的域名上bbs.newproxy.com,但是旧的域名(bbs.proxy.com)还可以正常使用。
配置:Nginx虚拟主机配置文件
bbs.proxy.com
server
{
listen 80;
server_name bbs.proxy.com;
index index.php index.html index.htm;
root /data/www/learn2.proxy.com;
error_log /data/weblogs/learn2_error.log crit;
access_log /data/wwwlogs/learn2.log access;
rewrite ^/(.*) http://bbs.newproxy.com/$1 permanent;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
bbs.newproxy.com
server {
listen 80;
server_name bbs.newproxy.com;
root /data/www/www.test.com;
index index.php index.html index.htm;
access_log /data/wwwlogs/rewrite.log access;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
红色字体为配置的rewrite规则,$1=(.*)
的内容,^/(.*)匹配所有,在这个环境里^任意开头,可以理解为^=bbs.proxy.com ,(.*)表示匹配所有
也就是bbs.proxy.com/aaaa
根据上述解释,可以得出:
如果访问bbs.proxy.com可以成功的跳转到bbs.newproxy.com
如果访问bbs.proxy.com/aaaa可以成功的跳转到bbs.newproxy.com
测试:
使用windows主机进行测试
在C:\Windows\System32\drivers\etc\hosts文件中添加host解析
192.168.110.46
bbs.newproxy.com
192.168.110.46
bbs.proxy.com
实验效果:
访问bbs.proxy.com 跳转到
bbs.newproxy.com
1、要访问的域名
2、成功跳转后的域名,但是这个是没有加参数的一个访问
3、加参数后的访问 bbs.proxy.com/blog/test.php
访问bbs.proxy.com 成功跳转到了bbs.newproxy.com站点 内容为rewrite ok
截图部分的两次验证分别是直接使用域名访问(bbs.proxy.com)和加参数的访问(bbs.proxy.com/blog/test.php)
但是这样的访问方式是直接受到 正则表达式 控制的
例1我在rewrite配置 只配置 ^/ ,那么无论你是用bbs.proxy.com或者bbs.proxy.com/blog/test.php这两种方式访问,最终只会跳转到bbs.newproxy.com
例2我在rewrite配置^/(.*),那么使用bbs.proxy.com或者bbs.proxy.com/blog/test.php,这两种方式访问就会实现加参数和不加参数的成功访问
^/(.*)和^/测试截图:
rewrite ^/ http://bbs.newproxy.com/$1 permanent;
同时访问bbs.proxy.com和bbs.proxy.com/blog/test.php,最终只会符合例1的分析
rewrite ^/(.*) http://bbs.newproxy.com/$1 permanent;
同时访问bbs.proxy.com和bbs.proxy.com/blog/test.php,例2分析,仔细看URL和内容是不一样的
2、实现不同域名的URL跳转
原域名:bbs.proxy.com
跳转域名:blog.proxy.com
Nginx虚拟主机配置
server
{
listen 80;
server_name
bbs.proxy.com;
index index.php
index.html index.htm;
root /data/www/learn2.proxy.com;
error_log
/data/weblogs/learn2_error.log crit;
access_log
/data/wwwlogs/learn2.log access;
if (
$http_host ~* "^(.*)\.proxy\.com$") {
set $domain
$1;
rewrite
^(.*) http://blog.proxy.com/$domain/test.php break;
}
location ~ \.php$ {
fastcgi_pass
127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param
SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
server {
listen 80;
server_name
blog.proxy.com;
root /data/www/www.test.com;
index index.php
index.html index.htm;
access_log
/data/wwwlogs/rewrite.log access;
location ~ \.php$ {
fastcgi_pass
127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param
SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
}
测试:
使用windows主机进行测试
在C:\Windows\System32\drivers\etc\hosts文件中添加host解析
192.168.110.46
bbs.proxy.com
192.168.110.46
blog.proxy.com
实验效果:
1)、访问,bbs.proxy.com,根据rewrite配置,
2)、参数解释
if ( $http_host ~* "^(.*)\.proxy\.com$") {
set $domain $1;
rewrite ^(.*) http://blog.proxy.com/$domain/test.php break;
}
$http_host:获取到客户端输入的域名,在测试环境中是bbs.proxy.com
$host:获取到客户端输入的域名,在测试环境中是bbs.proxy.com
$http_host和$host它们之间的区别是,如果是不同端口访问时,$http_host会显示端口(bbs.proxy.com:80,bbs.proxy.com:8080),但是$host是不会再后面追加端口
set $domain $1:$1=(.*),在这个环境中^(.*)=bbs,$domain=$1=bbs,也就是nginx匹配到的域名,可以理解为赋值给$domain
rewrite:不考虑变量等配置,实际的地址就是http://blog.proxy.com/bbs/test.php
$domain=bbs,使用这样的一种方式将匹配到的域名字符串绑定到了子目录
理解其含义就可以灵活配置了,例如$domain这个也可以不需要,直接在rewrite哪一行写上就可以
上述的配置是做了匹配到子目录的配置如果不需要也可以修改配置,不让其访问的子目录下
常用变量参数:
如果想看这些参数具体是什么内容,可以把这些参数写到
Nginx 日志格式里进行测试,这是我自己发现的方法,可能还有更好的办法
- $args :
#这个变量等于请求行中的参数,同$query_string - $content_length :
请求头中的Content-length字段。 - $content_type :
请求头中的Content-Type字段。 - $document_root : 当前请求在root指令中指定的值。
- $host : 请求主机头字段,否则为服务器名称。
- $http_user_agent : 客户端agent信息
- $http_cookie : 客户端cookie信息
- $limit_rate : 这个变量可以限制连接速率。
- $request_method :
客户端请求的动作,通常为GET或POST。 - $remote_addr : 客户端的IP地址。
- $remote_port : 客户端的端口。
- $remote_user : 已经经过Auth Basic
Module验证的用户名。 - $request_filename :
当前请求的文件路径,由root或alias指令与URI请求生成。 - $scheme : HTTP方法(如http,https)。
- $server_protocol :
请求使用的协议,通常是HTTP/1.0或HTTP/1.1。 - $server_addr :
服务器地址,在完成一次系统调用后可以确定这个值。 - $server_name : 服务器名称。
- $server_port : 请求到达服务器的端口号。
- $request_uri :
包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。 - $uri :
不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。 - $document_uri : 与$uri相同。
参数验证案例:例如我想知道$args
nginx.conf配置
log_format access ‘$args
$http_x_forwarded_for -
$remote_user [$time_local] "$request" ‘
‘$status $body_bytes_sent
"$http_referer" ‘
‘"$http_user_agent"
‘
‘"$request_time"
"$upstream_response_time" "$upstream_addr" ‘;
日志显示:注意观察字符串,位置不一定是第一
在https server下加入如下配置:
if ($uri !~* "/logging.php$")
{
rewrite ^/(.*)$ http://$host/$1 redirect;
}在http server下加入如下配置:
if ($uri ~* "/logging.php$")
{
rewrite ^/(.*)$ https://$host/$1 redirect;
}
server {
listen 80; server_name example.me; rewrite ^ https://$server_name$request_uri? permanent; ### 使用return的效率会更高 # return 301 https://$server_name$request_uri; }
原文地址:https://www.cnblogs.com/bazingafraser/p/8505072.html