为了探究nginx的url配置规则,固然须要安装nginx。我使用了vagrant建立了一个虚拟环境的ubuntu,经过apt-get安装nginx。这样就不会污染mac的软件环境。经过vragrant再建立一个项目进行实验。若是不了解vagrant的使用,能够查看Vagrant 虚拟环境利器。html
/vagrant
目录下建立了一个pro
用于项目的根目录,同时配置nginx
的配置文件(/etc/nginx/sites-enabled/pro.conf
)nginx
☁ pro tree . ├── 403.html ├── 404.html ├── index.html 0 directories, 3 files
pro.conf
的配置以下,即监听本机的80端口。web
server { listen 80 default_server; server_name localhost; access_log /var/log/nginx/pro/access.log; error_log /var/log/nginx/pro/error.log; error_page 404 /404.html; root /vagrant/pro; index index.html index.htm; }
上述的配置并无设置location
,可是配置了root /vagrant/pro
,访问http://192.168.33.10/
将会返回/vagrant/pro/index.html
。正则表达式
nginx的url匹配模式很强大,同时使用很是灵活,尤为是优先级的匹配,若是不寻找规律,不但很难掌握,并且容易犯晕。了解优先级以前,先看看匹配的配置语法,以及都有那些匹配模式。ubuntu
匹配的语法仍是很简单的:服务器
location [ = | ~ | ~* | ^~ ] uri { ... } location @name { ... }
没错,就这么多,实际写在loacation
中大概是这样的负载均衡
location = / { }
location [指令模式] url匹配模式 { }
指令模式指用于匹配的方式,即精确匹配,前缀匹配仍是正则匹配,固然这个是可选的,若是不写,则退化成正常匹配或者全匹配。url匹配模式则须要匹配的url,能够当作是web开发中的路由。下面就分别介绍指令模式和匹配模式。测试
=
指令用于精确字符匹配(模式),不能使用正则,区分大小写。为了直观的观察匹配命中的location,使用rewrite指令,用于转发。目前只要理解命中了就重定向到rewrite后面的url便可。google
location = /demo { rewrite ^ http://google.com; }
上述的配置表示只有访问 http://192.168.33.10/demo
这样的url,才能跳转到google的页面。除此以外的任何地址都没法访问,那怕是访问http://192.168.33.10/demo/
这个地址也不行。由于url匹配模式是/demo
。url
修改 location:
location = /demo$ { rewrite ^ http://google.com; }
熟悉正则的同窗初看会觉得/demo$
表示demo
结尾的url,其实否则,这里的$
符号也是url的一部分,只有访问http://192.168.33.10/demo$
这个地址才能跳转。
^~
指令用于字符前缀匹配,和=
精确匹配同样,也是用于字符肯定的匹配,不能使用正则且区分大小写。和=
不一样的在于,^~
指令下,访问的url无需url匹配模式如出一辙,只须要其开头前缀和url匹配模式同样便可。
location ^~ /demo { rewrite ^ http://google.com; }
对于该模式(/demo
),访问下列的地址都能匹配:
只须要以/demo
为前缀开头的url都能匹配。与该模式后的是否大小写无关。
^~
不支持正则。模式/demo$
中的$
并不表明字符模式结束,而是一个是实实在在的$
,只有访问/demo$
开头的url才能匹配,http://192.168.33.10/demo
则再也不匹配。
模式/[0-9]emo
也不表明正则中的http://192.168.33.10/0emo
、http://192.168.33.10/5emo
之类,只有访问以 /[0-9]emo
开头url才行,例如http://192.168.33.10/[0-9]emo
或http://192.168.33.10/[0-9]emo/aaa
前缀匹配一般用于匹配文件夹,如配置静态文件。
众所周知,nginx的url功能强大,配置灵活。字符匹配中,支持正则和不支持正则彻底是两个境界。前面的两种方式都不能使用正则,未免让人以为nginx有点虚夸。
实际上,nginx支持正则匹配。所使用的指令是~
和~*
,前者表示使用正则,区分大小写,后者表示使用正则,不区分大小写。与前缀匹配同样,正则匹配也是只需匹配以url模式开头的便可。
location ~ /[0-9]emo { rewrite ^ http://google.com; }
对于上述的模式,能够匹配的url以下:
只要是以正则表达式/[0-9]emo
匹配的字符开头的url,都能匹配。
使用~*
则不区分大小写
location ~ /[0-9]EmO { rewrite ^ http://google.com; }
下面的都能匹配
正常匹配的指令为空,即没有指定匹配指令的即为正常匹配。其形式相似 /XXX/YYY.ZZZ
正常匹配中的url匹配模式可使用正则,不区分大小写。
location /demo { rewrite ^ http://google.com; }
上述模式指的是匹配/demo
的url,下面的都能匹配
正常匹配和前缀匹配的差异在于优先级。前缀的优先级高于正常匹配
全匹配与正常匹配同样,没有匹配指令,匹配的url模式仅一个斜杠/
location / { rewrite ^ http://google.com; }
全匹配也能够配合 精确匹配和正则匹配一些指令,只不过这样的设定意义不大。经过都会有一个默认的location,这个就是全匹配。
命名匹配指的是使用@
比绑定一个模式,相似变量替换的用法。
error_page 404 = @not_found location @not_found { rewrite http://google.com; }
上述的做用是若是访问没有匹配的url会触发404指令,而后就匹配到@not_found
这个 location上。
nginx的匹配优先级遵循一个大原则和两个小细节。
大原则是关于匹配模式的优先级:
精确匹配 > 前缀匹配 > 正则匹配 > 正常匹配 > 全匹配
小细节则是同一优先级中:
=
精确匹配的优先级最高,这与配置的前后顺序无关
location ^~ /demo{ rewrite ^ http://google.com; } location = /demo { rewrite ^ http://baidu.com; }
访问
http://192.168.33.10/demo -> baidu.com http://192.168.33.10/demo/ggg -> google.com
尽管前缀匹配也能匹配/demo
这个地址,而且还先命中,但是=
的优先级更高。
再把前缀匹配换成正则匹配
location ~ /demo{ rewrite ^ http://google.com; } location = /demo { rewrite ^ http://baidu.com; }
访问结果仍然同样。精确匹配的优先级最高。
location ~ /[ad]emo{ rewrite ^ http://google.com; } location ^~ /demo { rewrite ^ http://baidu.com; }
上述两个模式中,第一个使用正则匹配,第二个使用前缀匹配,访问效果以下
http://192.168.33.10/demo -> baidu.com http://192.168.33.10/aemo -> google.com
因而可知,尽管也是正则匹配先命中规则,能够优先级低,仍是让步给前缀匹配。
location /demo/aa{ rewrite ^ http://google.com; } location ~ /[ad]emo { rewrite ^ http://baidu.com; }
http://192.168.33.10/demo/aa -> baidu.com http://192.168.33.10/aemo/aa -> baidu.com
访问/demo/aa
的地址的时候,尽管前者位置在前,而且也匹配最长,但是大规则的优先级,仍是要先进行后面的正则匹配。小细节也必须让步大规则。
location / { rewrite ^ http://google.com; } location /demo { rewrite ^ http://baidu.com; }
访问结果
http://192.168.33.10 -> index.html http://192.168.33.10/ -> google.comg http://192.168.33.10/demo -> baidu.com http://192.168.33.10/demo/aa -> baidu.com
因而可知,全匹配的优先级最低。
同级的匹配须要注意两个关键细节,是不是正则匹配,是不是最长匹配。
location /demo { rewrite ^ http://google.com; } location /demo/aa { rewrite ^ http://baidu.com; }
访问测试
http://192.168.33.10/demo -> google.com http://192.168.33.10/demo/aa -> baidu.com
第一个链接只匹配了第一个location,跳转google.com;第二个链接二者都匹配,但是第二个location的匹配字符更长,所以跳转了baidu.com。
把正常匹配换成前缀匹配的效果也同样。
location ^~ /demo { rewrite ^ http://google.com; } location ^~ /demo/aa { rewrite ^ http://baidu.com; }
访问结果以下:
http://192.168.33.10/demo -> google.com http://192.168.33.10/demo/aa -> baidu.com
经过上面的测试,可见同级的非正则的匹配,匹配结果最长的location最终会被命中。其实这个很好理解,匹配的字符越多,优先级越大嘛。可是为何这个原则要特指非正则的匹配呢?
正则匹配不适用最大匹配的原则,本质缘由是由于正则一旦匹配了,就中止匹配其余location,所以正则匹配与配置的前后顺序有关。
location ~ /demo { rewrite ^ http://google.com; } location ~ /demo/aa { rewrite ^ http://baidu.com; }
http://192.168.33.10/demo/aa -> http://google.com
nginx开始匹配location的模式,其中/demo
已经匹配了http://192.168.33.10/demo/aa
这个地址,所以中止搜索匹配其余的location。
下面更改一下上述配置的前后顺序:
location ~ /demo/aa { rewrite ^ http://baidu.com; } location ~ /demo { rewrite ^ http://google.com; }
访问测试:
http://192.168.33.10/demo/aa -> http://baidu.com
因而可知,正则匹配与匹配最大长度无关,只与匹配的前后顺序有关。
经过上述两个模式的测试,咱们对两个细节进行了倒序的推导。实际上使用记住两个细节会比较简单。判断同级的优先级概括以下:
面对一个location,先判断是不是正则匹配,若是是正则匹配,遇到匹配的模式,则命中。若是不是正则,则把匹配的模式放到一边,继续往下阅读配置,阅读完毕全部的匹配模式,查看哪种的匹配模式更长,则是最终命中的模式。
掌握nginx的location匹配优先级其实也不难,谨记一个原则两个细节,妈妈不再用担忧配错url啦。
nginx的url配置是使用nginx最基本功能。nginx做为服务器,它能够接收请求,处理请求,都是基于客户端url访问。掌握url的配置要了解配置的几个指令(=
,^~
)。熟悉每一个匹配模式的特色。
了解模式以后,对于优先级的断定,只需记住一个大的规则和两个细节,就能从容的应对了。
掌握url的配置以后,更重要的是在location域中作请求的处理。好比常见的静态文件配置,请求转发(rewrite),负载均衡等。
连接: