1、打开Nginx的rewrite日志
Nginx如果rewrite写了很多条,很容易发现rewrite写的没问题,可是就是匹配不了,很可能已匹配到其它rewrite中去了。打开rewrite的log,可以清晰的看到其匹配的先后顺序,和那一条匹配了。
方法:
1:在nginx.conf的http段加入如下:
rewrite_log on;
error_log logs/xxxerror.log notice;
注意两点:
1)在nginx.conf的http字段加。
2)注意 error_log的级别是notice,否则不会显示其具体的匹配过程,但需要注意,最好在测试环境下调试,error_log会增长的很快,我们网站20分钟5G多,所以在线上调试完了,尽快关闭!或改成error级别的。
好,那么怎么写rewrite重写呢?
location / { root /data/www/chinameat; index index.html index.php index.htm; rewrite "^/fwxts" /index.php?a=fwxts&m=index last; rewrite "^/fwxts.html" /index.php?a=fwxts&m=index last; rewrite "^/index.html" /index.php last; rewrite "index_index_info.html" /index.php?a=index&m=index_info last; rewrite "^/index_info.html" /index.php?a=index&m=index_info last; rewrite "^/detail_([0-9]+).html" /index.php?a=detail&id=$1 last; rewrite "^/list_([0-9]+).html" /index.php?a=list&id=$1 last; rewrite "^/list_([0-9]+)_([0-9]+).html" /index.php?a=list&id=$1&page=$2 last; rewrite "^/login.html" /index.php?a=login&m=login last; rewrite "^/reg.html" /index.php?a=login&m=reg last; rewrite "^/findpass.html" /index.php?a=login&m=findpass last; rewrite "^/download.html" /index.php?a=list&m=download last; rewrite "^/filedownload.html" /index.php?a=list&m=filedownload last; rewrite "^/file_center.html" /index.php?a=list&m=filedownload last; rewrite "^/chinameat_down.html" /index.php?a=list&m=download last; rewrite "^/rqd_down.html" /index.php?a=list&m=rqddownload last; rewrite "^/nc_down.html" /index.php?a=list&m=neicandownload last; rewrite "^/file_center.html" /index.php?a=list&m=filedownload last; rewrite "^/([a-zA-Z0-9_]+)_([a-zA-Z0-9_]+).html" /index.php?a=$1&m=$2 last; }
2.1 flag标志位
last
: 相当于Apache的[L]标记,表示完成rewritebreak
: 停止执行当前虚拟主机的后续rewrite指令集redirect
: 返回302临时重定向,地址栏会显示跳转后的地址permanent
: 返回301永久重定向,地址栏会显示跳转后的地址
因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:
last一般写在server和if中,而break一般使用在location中
last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
break和last都能组织继续执行后面的rewrite指令
2.2 if指令与全局变量
if判断指令
语法为if(condition){...}
,对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:
当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
直接比较变量和内容时,使用
=
或!=
~
正则表达式匹配,~*
不区分大小写的匹配,!~
区分大小写的不匹配
-f
和!-f
用来判断是否存在文件-d
和!-d
用来判断是否存在目录-e
和!-e
用来判断是否存在文件或目录-x
和!-x
用来判断文件是否可执行
2.3 常用正则
.
: 匹配除换行符以外的任意字符?
: 重复0次或1次+
: 重复1次或更多次*
: 重复0次或更多次\d
:匹配数字^
: 匹配字符串的开始$
: 匹配字符串的介绍{n}
: 重复n次{n,}
: 重复n次或更多次[c]
: 匹配单个字符c[a-z]
: 匹配a-z小写字母的任意一个
小括号()
之间匹配的内容,可以在后面通过$1
来引用,$2
表示的是前面第二个()
里的内容。正则里面容易让人困惑的是\
转义特殊字符。
全局变量
下面是可以用作if判断的全局变量
$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相同。
例:http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php
http://tengine.taobao.org/book/chapter_02.html
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
http://seanlook.com/2015/05/28/nginx-ssl/
Discuz!的重定向规则:
if (!-f $request_filename) {
rewrite ^/archiver/((fid|tid)-[\w\-]+\.html)$ /archiver/index.php?$1 last;
rewrite ^/forum-([0-9]+)-([0-9]+)\.html$ /forumdisplay.php?fid=$1&page=$2 last;
rewrite ^/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /viewthread.php?tid=$1&extra=page%3D$3&page=$2 last;
rewrite ^/space-(username|uid)-(.+)\.html$ /space.php?$1=$2 last;
rewrite ^/tag-(.+)\.html$ /tag.php?name=$1 last;
}