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;
}