文章目录
- 1. 概述
- 2. location格式
- 3. location匹配参数解释
- 4. location匹配顺序
- 4.1 匹配顺序精炼
- 5. 匹配问号后的参数
- 6. location URI结尾带不带/
- 7. 命名location
- 8. 案例
1. 概述
location
指令是nginx
中最关键的指令之一,location
指令的功能是用来匹配不同的url
请求,进而对请求做不同的处理和响应,这其中较难理解的是多个location
的匹配顺序,本文会作为重点来解释和说明。
nginx
用请求URI
与location中配置的URI做匹配。
2. location格式
location
有两种格式:
- 匹配
uri
类型,有四种参数可选,当然也可以不带参数。 - 命名
location
,用@
来标识,类似于定义goto
语句块。
location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
3. location匹配参数解释
参数 | 解释 |
空 |
|
~ | 执行一个正则匹配,区分大小写。 |
~* | 执行一个正则匹配,不区分大小写。 |
^~ | 普通字符匹配,多用来匹配目录。 |
= | 执行普通字符精确匹配。 |
@ | “@” 定义一个命名的 |
4. location匹配顺序
nginx
有两层指令来匹配请求URI
=>
第一个层次是server
指令,它通过域名
、ip
和端口
来做第一层级匹配,当找到匹配的server
后就进入此server
的location
匹配。location
的匹配并不完全按照它们在配置文件中出现的顺序来匹配,请求URI
会按如下规则跟server
里配置的location
匹配。
- 寻找有没有
“=”
等号参数完全匹配的location
,如果有完全匹配的等号location
则停止匹配,执行该location
中的指令,不去匹配其它类型的location
。 - 匹配所有非正则表达式
URI
的location
(包括空
,=
,^~
三种参数)。找到请求URI
和location URI
按前缀匹配最长的location
,如果这个最长的location
的参数是^~
,则停止匹配,执行该location
中的指令,否则暂存该location
。 - 匹配正则表达式
URI
的location
(包括~
,~*
两种参数),按location
在配置文件中出现的顺序匹配,如果找到第一个匹配的locaiton
则停止匹配,执行该location
。 - 匹配完所有正则表达式都没有匹配的
location
,则执行第二步中暂存的最长前缀匹配location
。
4.1 匹配顺序精炼
简单来说按这个规则:=
> ~^
> ~
= ~*
>最长前缀匹配
> /
5. 匹配问号后的参数
请求URI
中问号后面的参数是不能在location
中匹配到的,这些参数存储在$query_string
变量中,可以用if
来判断。
例如,对于参数中带有单引号'
进行匹配然后重定向到错误页面。
/plus/list.php?tid=19&mid=1124'
if ( $query_string ~* ".*[;'<>].*" ){
return 404;
}
6. location URI结尾带不带/
这个很多解释不太准确,有必要多说几句。
对于请求URI
结尾是否带有/
,一般的处理逻辑是带/
表示访问目录,不带/
表示访问文件,如果文件不存在也会去匹配目录。例如访问http://www.nginx.cn/images/
和http://www.nginx.cn/images
,前面的请求会匹配目录,后面的请求会先匹配文件,文件不存再匹配目录
对于locatioin
中的URI
来说,如果URI
的结尾带有/
,并且location
要执行的命令式是proxy_pass
、fastcgi_pass
、uwsgi_pass
、scgi_pass
、memcached_pass
、grpc_pass
之一。
例如:
location /images/ {
proxy_pass http://www.redis.com.cn
}
对于这种情况,nginx
会做特殊处理,不管images
命名的文件或目录存在不在,如果你访问http://www.nginx.cn/images
会被重定向到http://www.nginx.cn/images/
。
所以如果你想这两种请求对应不同的处理,就要明确增加不带/
结尾的location
配置。
location /images {
proxy_pass http://www.rabbitmq.cn
}
location /images/ {
proxy_pass http://www.redis.com.cn
}
7. 命名location
带有"@"
的location
是用来定义一个命名的location
,这种location
不参与请求匹配,一般用在内部定向。
例如用在error_page
, try_files
命令中。
它的功能类似于编程中的goto
。
location /images {
try_files $uri $uri/ @name;
}
location @name {
...
}
8. 案例
location = / {
// 只匹配请求 "/"
[ configuration A ]
}
location / {
// 匹配任何请求,因为所有请求都是以"/"开始
// 但是更长字符匹配或者正则表达式匹配会优先匹配
[ configuration B ]
}
location /documents/ {
// 匹配所有 /documents/ 开头的请求,在没有正则表达式匹配时选择该locaiton
[ configuration C ]
}
location ^~ /images/ {
// 匹配任何以 /images/ 开始的请求,并停止匹配其它location
[ configuration D ]
}
location ~* .(gif|jpg|jpeg)$ {
// 匹配以 gif, jpg, or jpeg结尾的请求.
// 但是所有 /images/ 目录的请求将由 [Configuration D]处理.
[ configuration E ]
}
请求URI
例子:
-
/
-> 匹配A
-
/index.html
-> 匹配B
-
/documents/a.html
-> 匹配C
-
/images/1.gif
-> 匹配D
-
/documents/1.jpg
-> 匹配E
(后续待补充)