Nginx 的语法形式是: location [=|~|~*|^~|@] /uri/ { … } ,意思是可以以“ = ”或“ ~* ”或“ ~ ”或“ ^~ ”或“ @ ”符号为前缀,当然也可以没有前缀(因为 [A] 是表示可选的 A ; A|B 表示 A 和 B 选一个),紧接着是 /uri/ ,再接着是{…} 指令块,整个意思是对于满足这样条件的 /uri/ 适用指令块 {…} 的指令。
上述各种 location 可分两大类,分别是:“普通 location ”,官方英文说法是 location using literal strings 和“正则 location ”,英文说法是 location using regular expressions 。其中“普通 location ”是以“ = ”或“ ^~ ”为前缀或者没有任何前缀的 /uri/ ;“正则 location ”是以“ ~ ”或“ ~* ”为前缀的 /uri/ 。
那么,当我们在一个 server 上下文编写了多个 location 的时候, Nginx 对于一个 HTTP 请求,是如何匹配到一个 location 做处理呢?用一句话简单概括 Nginx 的 location 匹配规则是:“正则 location ”让步 “普通 location”的严格精确匹配结果;但覆盖 “普通 location ”的最大前缀匹配结果。理解这句话,我想通过下面的实例来说明。
#1 先普通 location ,再正则 location周边不少童鞋告诉我, nginx 是“先匹配正则 location 再匹配普通 location ”,其实这是一个误区, nginx 其实是“先匹配普通 location ,再匹配正则 location ”,但是普通 location 的匹配结果又分两种:一种是“严格精确匹配”,官方英文说法是“ exact match ”;另一种是“最大前缀匹配”,官方英文说法是“ Literal strings match the beginning portion of the query – the most specific match will be used. ”。我们做个实验:
例题 1 :假设 nginx 的配置如下
server {
listen 9090;
server_name localhost;
location / {
root html;
index index.html index.htm;
deny all;
}
location ~ \.html$ {
allow all;
}
}
附录 nginx 的目录结构是: nginx->html->index.html
上述配置的意思是: location / {… deny all;} 普通 location 以“ / ”开始的 URI 请求(注意任何 HTTP 请求都必然以“/ ”开始,所以“ / ”的意思是所有的请求都能被匹配上),都拒绝访问; location ~\.html$ {allow all;} 正则 location以 .html 结尾的 URI 请求,都允许访问。
测试结果:
[root@web108 ~]# curl :9090/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor=”white”>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.1.0</center>
</body>
</html>
[root@web108 ~]# curl :9090/index.html
<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body bgcolor=”white” text=”black”>
<center><h1>Welcome to nginx!</h1></center>
</body>
</html>
[root@web108 ~]# curl :9090/index_notfound.html
<html>
<head><title>404 Not Found</title></head>
<body bgcolor=”white”>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.1.0</center>
</body>
</html>
[root@web108 ~]#
测试结果如下:
URI 请求 HTTP 响应curl :9090/ 403 Forbidden
curl :9090/index.html Welcome to nginx!
curl :9090/index_notfound.html 404 Not Found
curl :9090/ 的结果是“ 403 Forbidden ”,说明被匹配到“ location / {..deny all;} ”了,原因很简单HTTP 请求 GET / 被“严格精确”匹配到了普通 location / {} ,则会停止搜索正则 location ;