http://www.cnblogs.com/cgli/archive/2011/05/16/2047920.html

最近在VPS上尝试配置安装一个网站,VPS安装了LNMP(Linux+Nginx+MySQL+php)在配置重定规则的时候经常遇到一些问题,直接用Apache的规则到Nginx下没起作用。原来Apache 重写的规则到nginx上还有一些不太一样的地方。

这里只是简单记录一些学习示例,高手略过,新手可以看一下。

Nginx Rewrite规则相关指令
Nginx Rewrite规则相关指令有if、rewrite、set、return、break等,其中rewrite是最关键的指令。一个简单的Nginx Rewrite规则语法如下:

rewrite ^/b/(.*)\.html /play.php?video=$1 break;

如果加上if语句,示例如下:

if (!-f $request_filename)

rewrite ^/img/(.*)$ /site/$host/images/$1 last;

Nginx与Apache的Rewrite规则实例对比

简单的Nginx和Apache 重写规则区别不大,基本上能够完全兼容。例如:

Apache Rewrite 规则:

RewriteRule ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 [L]

RewriteRule ^/ceshi/$ /zl/ceshi.php [L]

RewriteRule ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 [L]

RewriteRule ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 [L]

Nginx Rewrite 规则:

rewrite ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 last;

rewrite ^/ceshi/$ /zl/ceshi.php last;

rewrite ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 last;

rewrite ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 last;

由以上示例可以看出,Apache的Rewrite规则改为Nginx的Rewrite规则,其实很简单:Apache的RewriteRule指令换成Nginx的rewrite指令,Apache的[L]标记换成Nginx的last标记,中间的内容不变。

如果Apache的Rewrite规则改为Nginx的Rewrite规则后,使用nginx -t命令检查发现nginx.conf配置文件有语法错误,那么可以尝试给条件加上引号。例如一下的Nginx Rewrite规则会报语法错误:

rewrite ^/([0-9]{5}).html$ /x.jsp?id=$1 last;

加上引号就正确了:
rewrite “^/([0-9]{5}).html$” /x.jsp?id=$1 last;

Apache与Nginx的Rewrite规则在URL跳转时有细微的区别:

Apache Rewrite 规则:
RewriteRule ^/html/tagindex/([a-zA-Z]+)/.*$ /$1/ [R=301,L]

Nginx Rewrite 规则:
rewrite ^/html/tagindex/([a-zA-Z]+)/.*$ http://$host/$1/ permanent;

以上示例中,我们注意到,Nginx Rewrite 规则的置换串中增加了“http://$host”,这是在Nginx中要求的。

另外,Apache与Nginx的Rewrite规则在变量名称方面也有区别,例如:

Apache Rewrite 规则:
RewriteRule ^/user/login/$ /user/login.php?login=1&forward=http://%{HTTP_HOST} [L]

Nginx Rewrite 规则:
rewrite ^/user/login/$ /user/login.php?login=1&forward=http://$host   last;

Apache与Nginx Rewrite 规则的一些功能相同或类似的指令、标记对应关系:

Apache的RewriteCond指令对应Nginx的if指令;
Apache的RewriteRule指令对应Nginx的rewrite指令;
Apache的[R]标记对应Nginx的redirect标记;
Apache的[P]标记对应Nginx的last标记;
Apache的[R,L]标记对应Nginx的redirect标记;
Apache的[P,L]标记对应Nginx的last标记;
Apache的[PT,L]标记对应Nginx的last标记;

允许指定的域名访问本站,其他域名一律跳转到http://www.aaa.com

Apache Rewrite 规则:
RewriteCond %{HTTP_HOST}    ^(.*?)\.domain\.com$
RewriteCond %{HTTP_HOST}    !^qita\.domain\.com$
RewriteCond %{DOCUMENT_ROOT}/market/%1/index.htm -f
RewriteRule ^/wu/$ /market/%1/index.htm [L]

Nginx的if指令不支持嵌套,也不支持AND、OR等多条件匹配,相比于Apache的RewriteCond,显得麻烦一些,但是,我们可以通过下一页的Nginx配置写法来实现这个示例:

Nginx Rewrite 规则:
if ($host ~* ^(.*?)\.domain\.com$) set $var_wupin_city $1;
     set $var_wupin ‘1′;

if ($host ~* ^qita\.domain\.com$)

set $var_wupin ‘0′;

if (!-f $document_root/market/$var_wupin_city/index.htm)

set $var_wupin ‘0′;

if ($var_wupin ~ ‘1′)

rewrite ^/wu/$ /market/$var_wupin_city/index.htm last;
}

rewrite 的语法

语法: rewrite regex replacement flag

默认: none

作用域: server, location, if

This directive changes URI in accordance with the regular expression
and the replacement string. Directives are carried out in order of
appearance in the configuration file.

这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。

Be aware that the rewrite regex only matches the relative path
instead of the absolute URL. If you want to match the hostname, you
should use an if condition, like so:

注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句。

rewrite只是会改写路径部分的东东,不会改动用户的输入参数,因此这里的if规则里面,你无需关心用户在浏览器里输入的参数,rewrite后会自动添加的因此,我们只是加上了一个?号和后面我们想要的一个小小的参数 ***https=1就可以了。

nginx的rewrite规则参考:

  1. ~ 为区分大小写匹配
  2. ~* 为不区分大小写匹配
  3. !~和!~*分别为区分大小写不匹配及不区分大小写不匹
  1. -f和!-f用来判断是否存在文件
  2. -d和!-d用来判断是否存在目录
  3. -e和!-e用来判断是否存在文件或目录
  4. -x和!-x用来判断文件是否可执行
  1. last 相当于Apache里的[L]标记,表示完成rewrite,呵呵这应该是最常用的
  2. break 终止匹配, 不再匹配后面的规则
  3. redirect 返回302临时重定向 地址栏会显示跳转后的地址
  4. permanent 返回301永久重定向 地址栏会显示跳转后的地址
  1. $args
  2. $content_length
  3. $content_type
  4. $document_root
  5. $document_uri
  6. $host
  7. $http_user_agent
  8. $http_cookie
  9. $limit_rate
  10. $request_body_file
  11. $request_method
  12. $remote_addr
  13. $remote_port
  14. $remote_user
  15. $request_filename
  16. $request_uri
  17. $query_string
  18. $scheme
  19. $server_protocol
  20. $server_addr
  21. $server_name
  22. $server_port
  23. $uri

结合QeePHP的例子

  1. if (!-d $request_filename) {
  2. rewrite ^/([a-z-A-Z]+)/([a-z-A-Z]+)/?(.*)$ /index.php?namespace=user&controller=$1&action=$2&$3 last;
  3. rewrite ^/([a-z-A-Z]+)/?$ /index.php?namespace=user&controller=$1 last;
  4. break;

多目录转成参数
abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2

  1. if ($host ~* (.*)\.domain\.com) {
  2. set $sub_name $1;
  3. rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last;
  4. }

目录对换
/123456/xxxx -> /xxxx?id=123456

  1. rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;

例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:

  1. if ($http_user_agent ~ MSIE) {
  2. rewrite ^(.*)$ /nginx-ie/$1 break;
  3. }

目录自动加“/”

  1. if (-d $request_filename){
  2. rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
  3. }

禁止htaccess

  1. location ~/\.ht {
  2. deny all;
  3. }

禁止多个目录

  1. location ~ ^/(cron|templates)/ {
  2. deny all;
  3. break;
  4. }

禁止以/data开头的文件
可以禁止/data/下多级目录下.log.txt等请求;

  1. location ~ ^/data {
  2. deny all;
  3. }

禁止单个目录
不能禁止.log.txt能请求

  1. location /searchword/cron/ {
  2. deny all;
  3. }

禁止单个文件

  1. location ~ /data/sql/data.sql {
  2. deny all;
  3. }

给favicon.ico和robots.txt设置过期时间;
这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志

  1. location ~(favicon.ico) {
  2. log_not_found off;
  3. expires 99d;
  4. break;
  5. }
  6. location ~(robots.txt) {
  7. log_not_found off;
  8. expires 7d;
  9. break;
  10. }

设定某个文件的过期时间;这里为600秒,并不记录访问日志

  1. location ^~ /html/scripts/loadhead_1.js {
  2. access_log   off;
  3. root /opt/lampp/htdocs/web;
  4. expires 600;
  5. break;
  6. }

文件反盗链并设置过期时间
这里的return 412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求
“rewrite ^/ http://leech.divmy.com/leech.gif;”显示一张防盗链图片
“access_log off;”不记录访问日志,减轻压力
“expires 3d”所有文件3天的浏览器缓存

  1. location ~* ^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$ {
  2. valid_referers none blocked *.c1gstudio.com *.c1gstudio.net localhost 208.97.167.194;
  3. if ($invalid_referer) {
  4. rewrite ^/ http://leech.divmy.com/leech.gif;
  5. return 412;
  6. break;
  7. }
  8. access_log   off;
  9. root /opt/lampp/htdocs/web;
  10. expires 3d;
  11. break;
  12. }

只充许固定ip访问网站,并加上密码

  1. root  /opt/htdocs/www;
  2. allow   208.97.167.194;
  3. allow   222.33.1.2;
  4. allow   231.152.49.4;
  5. deny    all;
  6. auth_basic “C1G_ADMIN”;
  7. auth_basic_user_file htpasswd;

将多级目录下的文件转成一个文件,增强seo效果
/job-123-456-789.html 指向/job/123/456/789.html

  1. rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;

将根目录下某个文件夹指向2级目录
如/shanghaijob/ 指向 /area/shanghai/
如果你将last改成permanent,那么浏览器地址栏显是/location/shanghai/

  1. rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

上面例子有个问题是访问/shanghai 时将不会匹配

  1. rewrite ^/([0-9a-z]+)job$ /area/$1/ last;
  2. rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

这样/shanghai 也可以访问了,但页面中的相对链接无法使用,
如./list_1.html真实地址是/area/shanghia/list_1.html会变成/list_1.html,导至无法访问。

那我加上自动跳转也是不行咯
(-d $request_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果

  1. if (-d $request_filename){
  2. rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
  3. }

知道原因后就好办了,让我手动跳转吧

  1. rewrite ^/([0-9a-z]+)job$ /$1job/ permanent;
  2. rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2 last;

文件和目录不存在的时候重定向:

  1. if (!-e $request_filename) {
  2. proxy_pass http://127.0.0.1;
  3. }

域名跳转

  1. server
  2. {
  3. listen       80;
  4. server_name  jump.88dgw.com;
  5. index index.html index.htm index.php;
  6. root  /opt/lampp/htdocs/www;
  7. rewrite ^/ http://www.88dgw.com/;
  8. access_log  off;
  9. }

多域名转向

  1. server_name  www.7oom.com/  www.divmy.com/;
  2. index index.html index.htm index.php;
  3. root  /opt/lampp/htdocs;
  4. if ($host ~ “c1gstudio\.net”) {
  5. rewrite ^(.*) http://www.7oom.com$1/ permanent;
  6. }

三级域名跳转

  1. if ($http_host ~* “^(.*)\.i\.c1gstudio\.com$”) {
  2. rewrite ^(.*) http://top.88dgw.com$1/;
  3. break;
  4. }

域名镜向

  1. server
  2. {
  3. listen       80;
  4. server_name  mirror.c1gstudio.com;
  5. index index.html index.htm index.php;
  6. root  /opt/lampp/htdocs/www;
  7. rewrite ^/(.*) http://www.divmy.com/$1 last;
  8. access_log  off;
  9. }

某个子目录作镜向

  1. location ^~ /zhaopinhui {
  2. rewrite ^.+ http://zph.divmy.com/ last;
  3. break;
  4. }

discuz ucenter home (uchome) rewrite

  1. rewrite ^/(space|network)-(.+)\.html$ /$1.php?rewrite=$2 last;
  2. rewrite ^/(space|network)\.html$ /$1.php last;
  3. rewrite ^/([0-9]+)$ /space.php?uid=$1 last;

discuz 7 rewrite

  1. rewrite ^(.*)/archiver/((fid|tid)-[\w\-]+\.html)$ $1/archiver/index.php?$2 last;
  2. rewrite ^(.*)/forum-([0-9]+)-([0-9]+)\.html$ $1/forumdisplay.php?fid=$2&page=$3 last;
  3. rewrite ^(.*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/viewthread.php?tid=$2&extra=page\%3D$4&page=$3 last;
  4. rewrite ^(.*)/profile-(username|uid)-(.+)\.html$ $1/viewpro.php?$2=$3 last;
  5. rewrite ^(.*)/space-(username|uid)-(.+)\.html$ $1/space.php?$2=$3 last;
  6. rewrite ^(.*)/tag-(.+)\.html$ $1/tag.php?name=$2 last;

给discuz某版块单独配置域名

  1. server_name  bbs.c1gstudio.com news.c1gstudio.com;
  2. location = / {
  3. if ($http_host ~ news\.divmy.com$) {
  4. rewrite ^.+ http://news.divmy.com/forum-831-1.html last;
  5. break;
  6. }
  7. }

discuz ucenter 头像 rewrite 优化

  1. location ^~ /ucenter {
  2. location ~ .*\.php?$
  3. {
  4. #fastcgi_pass  unix:/tmp/php-cgi.sock;
  5. fastcgi_pass  127.0.0.1:9000;
  6. fastcgi_index index.php;
  7. include fcgi.conf;
  8. }
  9. location /ucenter/data/avatar {
  10. log_not_found off;
  11. access_log   off;
  12. location ~ /(.*)_big\.jpg$ {
  13. error_page 404 /ucenter/images/noavatar_big.gif;
  14. }
  15. location ~ /(.*)_middle\.jpg$ {
  16. error_page 404 /ucenter/images/noavatar_middle.gif;
  17. }
  18. location ~ /(.*)_small\.jpg$ {
  19. error_page 404 /ucenter/images/noavatar_small.gif;
  20. }
  21. expires 300;
  22. break;
  23. }
  24. }

jspace rewrite

  1. location ~ .*\.php?$
  2. {
  3. #fastcgi_pass  unix:/tmp/php-cgi.sock;
  4. fastcgi_pass  127.0.0.1:9000;
  5. fastcgi_index index.php;
  6. include fcgi.conf;
  7. }
  8. location ~* ^/index.php/
  9. {
  10. rewrite ^/index.php/(.*) /index.php?$1 break;
  11. fastcgi_pass  127.0.0.1:9000;
  12. fastcgi_index index.php;
  13. include fcgi.conf;
  14. }

另外这里还有一个工具可以直接把apache规则转化为nginx规则

http://www.anilcetin.com/convert-apache-htaccess-to-nginx/

参考:

http://wiki.nginx.org/NginxChsHttpRewriteModule

http://blog.csdn.net/cnbird2008/archive/2009/08/04/4409620.aspx

http://www.divmy.com/

[转】 nginx rewrite规则的更多相关文章

  1. Nginx Rewrite规则记录

    Rewrite 是一种服务器的重写脉冲技术,它可以使得服务器可以支持 URL 重写,是一种最新流行的服务器技术.它还可以实现限制特定IP访问网站的功能.很多情况下,某个 IP 的访问很容易造成 CPU ...

  2. Nginx rewrite 规则 与 proxy_pass 实现

    Nginx rewrite 规则  与 proxy_pass 实现     -------------------------------------------------------------- ...

  3. Nginx Rewrite规则详解

    Rewrite规则含义就是某个URL重写成特定的URL,从某种意义上说为了美观或者对搜索引擎友好,提高收录量及排名等. Rewrite规则的最后一项参数为flag标记,支持的flag标记主要有以下几种 ...

  4. Nginx系列二:(Nginx Rewrite 规则、Nginx 防盗链、Nginx 动静分离、Nginx+keepalived 实现高可用)

    一.Nginx Rewrite 规则 1. Nginx rewrite规则 Rewrite规则含义就是某个URL重写成特定的URL(类似于Redirect),从某种意义上说为了美观或者对搜索引擎友好, ...

  5. [转帖]Nginx rewrite 规则 与 proxy_pass 实现

    Nginx rewrite 规则 与 proxy_pass 实现 https://www.cnblogs.com/jicki/p/5546916.html Nginx rewrite 规则  与 pr ...

  6. Nginx Rewrite规则

    location = / { # 精确匹配 / ,主机名后面不能带任何字符串 [ configuration A ] } location / { # 因为所有的地址都以 / 开头,所以这条规则将匹配 ...

  7. codeigniter nginx rewrite规则配置【转】

    转自:http://www.nginx.cn/1134.html nginx如何配置才能支持codeigniter ? 1. codeigniter的url美化去掉index.php   1 2 3 ...

  8. Nginx Rewrite规则初探(转)

    Nginx  rewrite(nginx url地址重写)Rewrite 主要的功能就是实现URL的重写,Nginx的Rewrite规则采用Pcre,perl兼容正则表达式的语法规则匹配,如果需要Ng ...

  9. 【Web】Nginx Rewrite规则

    Rewrite介绍 Rewrite主要的功能就是实现URL的重写,Nginx的Rewrite规则采用Pcre,perl兼容正则表达式的语法规则匹配,如果需要Nginx的Rewrite功能,在编译Ngi ...

随机推荐

  1. (27)zabbix自定义图表Graph

    zabbix提供了一个自定义图表的功能,这不是废话么?呵呵~前面文章 讲到的<zabbix简易图表>只能显示单个item的数据图表.如果我们想显示多个信息到一个图表上,那必须使用zabbi ...

  2. python 有4个数字1234,能组成多少个互不相同且无重复的三位数数字。

    def output(): count = 0 for i in range(1,5): for j in range(1, 5): for k in range(1, 5): if i==j or ...

  3. python datetime,time时间格式和用法

    我是转载的这个大神的   他的网址:https://www.cnblogs.com/wanglinjie/p/9226926.html #以下是time的方法 >>> import ...

  4. ZOJ 2058 The Archaeologist's Trouble II(贪心+模拟)

    [题目大意] 一个n高的塔,由@ * ?三种字符组成.每行相邻两个字符不能相邻. '?' 表示未确定是 '@' 还是 '*' . 求'@' 可能出现的最多和最少次数. [分析] 在可以填的情况下 先填 ...

  5. DFS:POJ3620-Avoid The Lakes(求最基本的联通块)

    Avoid The Lakes Time Limit: 1000MS Memory Limit: 65536K Description Farmer John's farm was flooded i ...

  6. 基于顺序链表的栈的顺序存储的C风格实现

    头文件: #ifndef _SEQSTACK_H_ #define _SEQSTACK_H_ typedef void SeqStack; //创建一个栈 SeqStack* SeqStack_Cre ...

  7. CodeForces 484B 数学 Maximum Value

    很有趣的一道题,题解戳这. #include <iostream> #include <cstdio> #include <cstring> #include &l ...

  8. <题解>洛谷P3385 【模板】负环

    题目链接 判断一张图中是否存在关于顶点1的负环: 可以用SPFA跑一遍,存在负环的情况就是点进队大于n次 因为在存在负环的情况下,SPFA会越跑越小,跑进死循环 在最差的情况下,存在的负环长度是“n+ ...

  9. mysql无法启动,报错 Can't start server: can't create PID file: No space left on device

    然后看mysql日志文件 出现Can't start server: can't create PID file: No space left on device 这个错误. 提示磁盘空间不足 后用d ...

  10. Python内置函数7

    Python内置函数7 1.propertypython内置的一个装饰器可参考https://blog.csdn.net/u013205877/article/details/77804137 2.q ...