、Nginx正则及location匹配

1、Nginx location规则匹配

^~ 标识符匹配后面跟一个字符串。匹配字符串后将停止对后续的正则表达式进行匹配,如location ^~ /images/,在匹配了/images/这个字符串后就停止对后续的正则匹配

= 精准匹配,如location = /,只会匹配url为/的请求-> http://www.a.com/

~ 区分大小写的匹配 -> location ~ \.jsp$

~* 不区分大小写的匹配-> location ~* \.jsp$

!~ 对区分大小写的匹配取非

!~* 对不区分大小写的匹配取非

/ 通用匹配, 如果没有其它匹配,任何请求都会被匹配到

2、正则表达式

* 重复前面的字符0次或多次

? 重复前面的字符0次或1次

+ 重复前面的字符1次或多次

. 匹配除换行符以外的任意1个字符

(a|b) 匹配a或b

^ 以…开头

$ 以…结尾

{n} 重复前面的字符n次

{n,} 重复前面的字符n次或更多次

{n,m} 重复前面的字符n到m次

*? 重复前面的字符0次或多次,但尽可能少重复

+? 重复前面的字符1次或更多次,但尽可能少重复

?? 重复前面的字符0次或1次,但尽可能少重复

{n,m}? 重复前面的字符n到m次,但尽可能少重复

{n,}? 重复前面的字符n次以上,但尽可能少重复

3、正则表达式补充:

\W 匹配任意不是字母,数字,下划线,汉字的字符

\S 匹配任意不是空白符的字符

\D 匹配任意非数字的字符

\B 匹配不是单词开头或结束的位置

[a] 匹配单个字符a

[a-z] 匹配a-z小写字母的任意一个

[^a] 匹配除了a以外的任意字符

[^abc] 匹配除了abc这几个字母以外的任意字符

4、Nginx location应用规则

location [=|~|~*|^~|!~|!~*|/] /url/{...}

默认值:no

使用字段:server

location参数根据URL的不同需求来进行配置,可以使用字符串与正则表达式匹配,


location ~* .*\.jsp$ {

proxy_pass http://tomcat_server;

}

location = / {

# 精确匹配 / ,主机名后面不能带任何字符串

[ configuration A ]

}



location / {

# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求

# 但是正则和最长字符串会优先匹配

[ configuration B ]

}



location /documents/ {

# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索

# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条

[ configuration C ]

}



location ~ /documents/abc {

# 匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索

# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条

[ configuration CC ]

}



location ^~ /images/ {

# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。

[ configuration D ]

}



location ~* \.(gif|jpg|jpeg)$ {

# 匹配所有以gif,jpg或jpeg 结尾的请求

# 然而,所有请求 /images/ 下的图片会被config D 处理,因为 ^~ 到达不了这一条正则

[ configuration E ]

}



location /images/ {

# 字符匹配到 /images/,继续往下,会发现 ^~ 存在

[ configuration F ]

}



location /images/abc {

# 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在

# F与G的放置顺序是没有关系的

[ configuration G ]

}



location ~ /images/abc/ {

# 只有去掉config D 才有效:先最长匹配config G 开头的地址,继续往下搜索,匹配到这一条正则,采用

[ configuration H ]

匹配顺序优先级:

(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

按照上面的location匹配,分析以下案例:


/ ->config A

精确完全匹配,即使/index.html也匹配不了



/downloads/download.html ->config B

匹配B以后,往下没有任何匹配,采用B



/images/1.gif -> config D

匹配到B,往下匹配到D,停止往下



/images/abc/def ->config D

最长匹配到G,往下匹配D,停止往下

你可以看到 任何以/images/开头的都会匹配到D并停止,FG写在这里是没有任何意义的,H是永远轮不到的,这里只是为了说明匹配顺序



/documents/document.html ->config C

匹配到C,往下没有任何匹配,采用C



/documents/1.jpg -> configuration E

匹配到C,往下正则匹配到E



/documents/abc ->config CC

最长匹配到C,往下正则顺序匹配到CC,往下到E

实际使用建议

        所以实际使用中,个人觉得至少有三个匹配规则定义,如下:

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理。这里是直接转发给后端应用服务器了,也可以是一个静态首页。

# 第一个必选规则

location = / {

proxy_pass http://tomcat:8080;

}



# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项

# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用

location ^~ /static/ {

root /usr/local/nginx/html/static/;

}

location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {

root /webroot/res/;

}



#第三个规则就是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认是动态请求,自己根据实际把握。

#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了

location / {

proxy_pass http://tomcat:8080;

}

二、Nginx Rewrite规则

        Nginx Rewrite功能是使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现URL重写以及重定向功能。Rewrite指令只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用。

        Nginx的Rewrite规则采用PCRE(Perl compatible Regular Expressions,Perl兼容正则表达式)的语法进行规则匹配,如果需要Nginx的Rewrite功能,在编译安装Nginx之前,必须安装PCRE库。

例如:http://www.crushlinux.com/a/we/index.php?id=1&u=admin只对URL中的/a/we/index.php等字符串起作用。

URL是Uniform Resource Location的缩写,译为“统一资源定位符”。

语法:

rewrite 正则表达式 更换目标 [标志位];

        rewrite和location功能有点像,都能实现跳转。主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对路径做控制访问或反向代理,可以使用proxy_pass代理到其他机器。很多情况下rewrite也会写在location里,它们的执行顺序是:

  1. 执行server块的rewrite指令
  2. 执行location匹配
  3. 执行选定的location中的rewrite指令

        注意:如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。

flag标志位

  1. last : 相当于Apache的[L]标记,表示完成rewrite
  2. break : 本条规则匹配完成后,终止匹配,不再匹配后面的规则
  3. redirect : 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址
  4. permanent : 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址

last一般写在server和if中,而break一般使用在location中

last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配

break和last都能组织继续执行后面的rewrite指令

last和break用来实现URI重写,浏览器地址栏URL地址不变

redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址

if指令与全局变量

if判断指令

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

当表达式只是一个变量时,如果其值为空或任何以0开头的字符串时都会当作条件为false

直接比较变量和内容时,

使用=或!=

-f和!-f 用来判断是否存在文件

-d和!-d 用来判断是否存在目录

-e和!-e 用来判断是否存在文件或目录

-x和!-x 用来判断文件是否可执行

例如: http://www.a.com/msie/a/b/test.html

        

if ($http_user_agent ~ MSIE) {

rewrite ^(.*)$ /msie/$1 break;

}

//如果UA包含"MSIE",rewrite请求到/msie/目录下



if ($request_method = POST) {

return 405;

} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302



注意:因为返回301和302不能只返回状态码,还必须有重定向的URL,所以return指令无法返回301,302。



if ($slow) {

limit_rate 10k;

} //限速,$slow可以通过 set 指令设置



if (!-f $request_filename){

break;

proxy_pass http://127.0.0.1;

} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查



if ($args ~ post=140){

rewrite ^ http://example.com/ permanent;

} //如果query string中包含"post=140",永久重定向到example.com

Nginx变量

下面是可以用作if判断的变量

$args: 记录请求行中的参数,同$query_string

$content_length: 记录请求头中的Content-length字段。

$content_type: 记录请求头中的Content-Type字段。

$document_root: 记录当前请求在root指令中指定的值。

$host : 记录请求主机头字段,否则为服务器名称。

$http_user_agent: 记录用于记录客户端浏览器的相关信息

$http_cookie: 记录客户端cookie信息

$limit_rate: 记录可以限制连接速率。

$request_method: 记录客户端请求的动作,通常为GET或POST。

$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.php”。

$document_uri: 与$uri相同。

$http_x_forwarded_for 记录远程客户端的ip地址

$remote_addr: 记录远程客户端的IP地址。

$remote_port: 记录远程客户端的端口。

$remote_user 记录远程客户端用户名称

$time_local 记录访问时间及时区

$request 记录请求的URL与HTTP协议

$status 记录请求的状态,例如成功时为200,页面找不到时为404

$body_byte_sent 记录发送给客户端的文件主体内容大小

$http_referer 记录是从哪个页面链接访问过来的

URL分析:

http://localhost:88/test1/test2/test.php

$host:localhost

$server_port:88

$request_uri:http://localhost:88/test1/test2/test.php

$documenturi:/test1/test2/test.php

$document_root:/var/www/html

$request_filename:/var/www/html/test1/test2/test.php



Nginx日志案例:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

'$status $body_bytes_sent "$http_referer" '

'"$http_user_agent" "$http_x_forwarded_for"';

//IP地址-用户名 [本地时间] “请求”

//状态码主体内容大小“访问来源链接”

  //”浏览器信息”“客户端IP地址”

192.168.200.2 - -[21/Nov/2016:10:14:57 +0800]"GET / HTTP/1.1"3040"-""Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)"

示例,如果访问的URL以"*.sh" "*.bash"结尾,则返回状态码403

location ~ .*\.(sh|bash)?$

{

return 403;

}

将原来要访问/data目录重写为/bbs

rewrite ^/data/?$ /bbs/ permanent;

rewrite ^/data/(.*)$ /bbs/$1 permanent;

防止盗链

​
localtion ~*\.(gif|jpg|png|swf|flv)${

valid_referers none blocked www.test.com *.test.com;

if($incalid_referer){

rewrite ^/(.*) http://www.test.com/block.html break;

}

}

​

实现域名跳转

所有对www.360buy.com的访问,rewrite到www.jd.com

server {

listen       80;

server_name  www.jd.com;

charset utf-8;

root   html;

index  index.html index.htm;

if ($host = "www.360buy.com") {

rewrite ^(.*)$ http://www.jd.com/$1 permanent;

}

}

将访问www.baidu.com下的所有请求转发到http://www.baidu.com@123/

if ($host = "www.baidu.com") {

rewrite ^(.*)$ http://www.baidu.com@123/$1 permanent;

}

三、Nginx静动分离

实验环境:两台服务器

192.168.200.111 Nginx服务器

192.168.200.112 LAMP服务器

LAMP rpm方式搭建

[root@localhost ~]# yum -y install httpd mariadb mariadb-devel mariadb-server php

[root@localhost ~]# systemctl start httpd

[root@localhost ~]# systemctl start mariadb

[root@localhost ~]# cat /var/www/html/index.php

<?php

phpinfo();

?>

宿主机测试:

配置Nginx动静分离

修改nginx.conf主配置文件

        location ~* \.(png|bmp|jpg)$ {

            root /usr/local/nginx/html/images;

        }

        location ~* \.php$ {

            proxy_pass http://192.168.200.112;

        }

浏览器访问测试图片文件:

[root@nginx ~]# cd /usr/local/nginx/html/

[root@nginx html]# tree

.

├── 50x.html

├── images

│?? └── linux.png

└── index.html



1 directory, 3 files

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐