Nginx正则表达式与HttpRewrite模块

nginx 正则表达式使用的是PCRE,PCRE库是一组函数,它们使用与Perl 5相同的语法和语义实现正则表达式模式匹配.PCRE具有自己的本机API,以及一组与POSIX正则表达式API对应的包装函数。PCRE库是免费的,即使是用于构建专有软件。

PCRE最初是为Exim MTA编写的 ,但现在被许多备受瞩目的开源项目使用,包括 Apache, PHP, KDE, Postfix和 Nmap。PCRE还进入了一些着名的商业产品,如 Apple Safari。使用PCRE的其他一些有趣项目包括 Chicken, Ferite, Onyx, Hypermail, Leafnode, Askemos, Wenlin和 8th。

常用正则匹配符

  • . : 匹配除换行符以外的任意字符
  • ? : 重复0次或1次
  • + : 重复1次或更多次
  • * : 重复0次或更多次
  • \d :匹配数字
  • ^ : 匹配字符串的开始
  • $ : 匹配字符串的介绍
  • {n} : 重复n次
  • {n,} : 重复n次或更多次
  • [c] : 匹配单个字符c
  • [a-z] : 匹配a-z小写字母的任意一个

注:小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容。

正则表达式测试工具

$ echo 'a.gif' | grep -P '\.(jp?g|gif|bmp|png)'

#输出
a.gif

全局变量


* $args					请求中的参数;
* $binary_remote_addr	远程地址的二进制表示
* $body_bytes_sent		已发送的消息体字节数
* $content_length		HTTP请求信息里的"Content-Length";
* $content_type			请求信息里的"Content-Type";
* $document_root		针对当前请求的根路径设置值;
* $document_uri			与$uri相同;
* $host					请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
* $hostname
* $http_cookie			cookie 信息
* $http_post
* $http_referer			引用地址
* $http_user_agent		客户端代理信息
* $http_via				最后一个访问服务器的Ip地址。http://www.cnblogs.com/deng02/archive/2009/02/11/1387911.html
* $http_x_forwarded_for	相当于网络访问路径。http://www.cnblogs.com/craig/archive/2008/11/18/1335809.html
* $is_args
* $limit_rate			对连接速率的限制;
* $nginx_version
* $pid
* $query_string			与$args相同;
* $realpath_root
* $remote_addr			客户端地址;
* $remote_port			客户端端口号;
* $remote_user			客户端用户名,认证用;
* $request				用户请求
* $request_body
* $request_body_file	发往后端的本地文件名称
* $request_completion
* $request_filename		当前请求的文件路径名
* $request_method		请求的方法,比如"GET"、"POST"等;
* $request_uri			请求的URI,带参数;
* $scheme				所用的协议,比如http或者是https,比如rewrite^(.+)$$scheme://example.com$1redirect;
* $sent_http_cache_control
* $sent_http_connection
* $sent_http_content_length
* $sent_http_content_type
* $sent_http_keep_alive
* $sent_http_last_modified
* $sent_http_location
* $sent_http_transfer_encoding
* $server_addr			服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
* $server_name			请求到达的服务器名;
* $server_port			请求到达的服务器端口号;
* $server_protocol		请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
* $uri						请求的URI,可能和最初的值有不同,比如经过重定向之类的。

HttpRewrite模块

该模块允许使用正则表达式改变URI,并且根据变量来转向以及选择配置。如果在server级别设置该选项,那么他们将在location之前生效。如果在location还有更进一步的重写规则,location部分的规则依然会被执行。如果这个URI重写是因为location部分的规则造成的,那么location部分会再次被执行作为新的URI

break 指令

语法 break

作用域:server,location,if

作用是完成当前的规则列

示例

if ($slow) {
: limit_rate  10k;
: break;
}

if 指令

if判断指令
语法为if(condition){…},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:

作用域: server, location

  • 当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
  • 直接比较变量和内容时,使用=或!=
  • 正则表达式匹配,*不区分大小写的匹配,!~区分大小写的不匹配

-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行

示例

if ($http_user_agent ~ MSIE) {
: rewrite  ^(.*)$  /msie/$1  break;
}
if ($http_cookie ~* "id=([^;] +)(?:;|$)" ) {
: set  $id  $1;
}
if ($request_method = POST ) {
: return 405;
}
if (!-f $request_filename) {
: break;
: proxy_pass  http://127.0.0.1;
}
if ($slow) {
: limit_rate  10k;
}
if ($invalid_referer) {
: return   403;
}

return指令

语法:return code

作用域: server, location, if

这个指令根据规则的执行情况,返回一个状态值给客户端。可使用值包括:204,400,402-406,408,410,411,413,416以及500-504。也可以发送非标准的444代码-未发送任何头信息下结束连接

rewrite指令

语法: rewrite regex replacement flag

默认: none

作用域: server, location, if

这个指令根据表达式来更改URI,或者修改字符串。指令根据配置文件中的顺序来执行。
注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,如下

if ($host ~* www\.(.*)) {
: set $host_without_www $1;
: rewrite ^(.*)$ http://$host_without_www$1 permanent; # $1 contains '/foo', not 'www.mydomain.com/foo'
}

需要注意的是rewrite后面的第一个正则参数永远是只对URI进行匹配,而不是对完整的带主机头的URL,如上例中,if语句来判断主机头,如果匹配www.(.*),则设置一个变量KaTeX parse error: Can't use function '\.' in math mode at position 23: …thout_www的值为www\̲.̲(.*)的引用,如果上例中的请…host_without_www的值为mydomain.com,而下面的rewrite指令中,第一个正则表达式的引用将为/foo,则最终通过这个重写后的请求URL为http://mydomain.com/foo

location ~*  ^/static/.*\.jpg$ {
        root /usr/share/nginx/html/;
        rewrite /static/css/(.*)$ /$1 ;
    }

匹配/static/开头,.jpg 结尾的请求中,将所有/static/css/开头的请求去掉/static/css

  • 示例三

nginx rewrite 实现二级域名跳转
当访问http://abc.jbxue.com跳转到http://www.jbxue.com/test/abc/

方法一:这种方法浏览器地址会变www.jbxue.com/test/abc

server {
        listen 80;
        server_name www.jbxue.com;
        location / {
                root /data/test;
                index index.html;
        }
}
server {
        listen 80;
        server_name *.jbxue.com;
        if ( $http_host ~* "^(.*)\.jbxue\.com$") {
                set $domain $1;
                rewrite ^(.*) http://www.jbxue.com/test/$domain/ break;
        }
}

方法二:当访问http://abc.jbxue.com跳转到http://www.jbxue.com/test/abc/

server {
        listen 80;
        server_name *.jbxue.com;
        root /usr/local/www;
        #这是里可以加多个目录,如果不加目录,会无法访问到abc.jbxue.com/目录下的文件,如图片目录/images
        location ~ ^/(jbxue|images|styles)/
        {
                proxy_redirect        off;
                proxy_set_header    Host   www.jbxue.com;
                proxy_pass      http://192.168.1.2:8080;
        }
        location / {
                set $domain default;
                if ( $http_host ~* "^(.*)\.jbxue\.com$") {
                        set $domain $1;
                }
                rewrite ^/(.*)    /test/$domain/$1 last;
        }
        access_log off;
}

标志位

  • last : 相当于Apache的[L]标记,表示完成rewrite
  • break : 停止执行当前虚拟主机的后续rewrite指令集
  • redirect : 返回302临时重定向,地址栏会显示跳转后的地址
  • permanent : 返回301永久重定向,地址栏会显示跳转后的地址
    因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:
  1. last一般写在server和if中,而break一般使用在location中
  2. last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
  3. break和last都能组织继续执行后面的rewrite指令

set 指令

语法:设置变量值

作用域:server,location,if

指令为指示的变量建立值。 作为值,可以使用文本,变量及其组合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值