Nginx配置location语法规则

语法规则

基本语法:

1
2
3
location [=|~|~*|^~|@] /uri/ {
...
}

修饰符释义:

修饰符 释义
= 表示精确匹配后面的url
~ 表示正则匹配,但是区分大小写
~* 表示正则匹配,不区分大小写
^~ 表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录
@ “@” 定义一个命名的 location,使用在内部定向时,例如 error_page
/ 通用匹配,任何请求都会匹配到

上述匹配规则的优先匹配顺序:

  • = 前缀的指令严格匹配这个查询。如果找到,停止搜索;
  • 所有剩下的常规字符串,最长的匹配。如果这个匹配使用 ^~ 前缀,搜索停止;
  • 正则表达式,在配置文件中定义的顺序;
  • 如果第 3 条规则~*产生匹配的话,结果被使用。否则,使用第 2 条规则~的结果。

匹配案例

通过精确匹配

配置文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
...

location /test.html {
root /www/wwwroot/nginx/html;
}

location = /test.html {
root /www/wwwroot/nginx/test.html;
}

...
}

两个location匹配条件一样,都是/test.html,但是第二个为精确匹配到静态文件路径,因此第一个不会执行,会执行第二个。

指定静态资源路径用的关键字root,还可以用alias,那么rootalias的区别是什么?

  • root属性指定的值是要加入到最终路径中的,匹配条件会拼接到路径中
  • alias属性指定的值不需要加入到最终路径中

根据上述配置文件内容,请求的条件为test.html,通过root指定的路径为/www/wwwroot/nginx/html,因此在匹配的时候,这个路径下就必须要有test.html这个文件才可以,否则就会找不到而报错,如果用alias,那么通过浏览器进行请求的时候,alias也是指定到/www/wwwroot/nginx/html路径下,但是会匹配默认的index.html,而无须强制匹配test.html,但是此时就不能使用=来进行精确匹配,现在将root改为alias

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
...

location /test.html {
alias /www/wwwroot/nginx/html/;
}

...
}

注意:alias指定的路径结尾要加/

来个rootalias的区别例子

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
...

location /html/ {
root /www/wwwroot/nginx;
}

...
}

访问 域名/html 的时候,将跳转到/www/wwwroot/nginx/html/目录下的index.html文件

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
...

location /html_alias/ {
alias /www/wwwroot/nginx/html/;
}

...
}

访问 域名/html_alias 的时候,将跳转到/www/wwwroot/nginx/html/目录下的index.html文件

通过^~方式实现匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 80;
...

location ^~ /a/ {
return 111;
}

location ^~ /a/b/ {
return 222;
}

...
}
  • 如果访问 域名/a 返回 111
  • 如果访问 域名/a/b 返回 222
  • 如果访问 域名/a/b/sdf 返回 222

从结果看,两条规则同时被匹配成功,但是第二条规则比较长,因此第二条规则优先被匹配,如果^~匹配成功了,那么表示阻断正则表达式,不再进行正则匹配。

通过~方式实现匹配

在匹配最长规则的时候,除了通过^~来实现匹配,还有通过普通匹配来实现。

当最长规则是通过普通匹配的时候,将会继续正则匹配, 只要有一个正则成功,则使用这个正则的location,停止继续匹配,返回结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
...

location ^~ /a/ {
return 111;
}

location /a/b/ {
return 222;
}

location ~ /a/b/ {#区分大小写的正则匹配
return 333;
}
...
}
  • 如果访问 域名/a 返回 111
  • 如果访问 域名/a/b 返回 333
  • 如果访问 域名/a/b/sdf 返回 333

从结果看,可以看出请求/a/b/的时候,首先会到达第二条规则(最长规则),由于第二条规则为普通匹配(不是^~匹配),因此会继续去匹配正则,也就是第三条规则,因此最终返回333

通过~*方式实现匹配

~* 表示不区分大小写的正则匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
...

location ^~ /a/ {
return 111;
}

location /a/b/ {
return 222;
}

location ~* /a/b/ {#不区分大小写的正则匹配
return 333;
}
...
}
  • 如果访问 域名/a/b/sdf 返回 333
  • 如果访问 域名/A/B/sdf 返回 333

从结果看,无论匹配的是大写还是小写,都会返回333

常用方法还有匹配图片后缀,并返回指定信息,如:

1
2
3
4
5
6
7
8
9
server {
listen 80;
...

location ~* \.(gif|jpg|png) {#不区分大小写,并以gif|jpg|png后缀结尾
return 444;
}
...
}
  • 如果访问 域名/a.jpg 返回 444
  • 如果访问 域名/A.JPG 返回 444

通过/ 实现通用匹配

  1. proxy_pass(代理转发)最后面没有斜杠,匹配路径有斜杠(/aaa/)
1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
...

location /aaa/ {
proxy_pass http://127.0.0.1:8081;
proxy_rediect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}

proxy_pass最后面没有斜杠/,此时通过浏览器请求http://域名/aaa/,那么实际访问的地址就是 http://127.0.0.1:8081/aaa/,会将匹配路径/aaa一起加过去。

  1. proxy_pass最后面有斜杠/,匹配路径也有斜杠(/aaa/)
1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
...

location /aaa/ {
proxy_pass http://127.0.0.1:8081/;
proxy_rediect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}

proxy_pass最后面有斜杠/,此时通过浏览器请求http://域名/aaa/,那么实际访问的地址就是 http://127.0.0.1:8081,会将/aaa抛弃的。

  1. proxy_pass后面还有其他路径但是最后没有 /, 匹配路径也有斜杠(/aaa/)
1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
...

location /aaa/ {
proxy_pass http://127.0.0.1:8081/bbb;
proxy_rediect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}

此时通过浏览器访问http://域名/aaa/index.html,实际请求的是http://127.0.0.1:8081/bbbindex.html(注意位置是默认路径下,不是`bbb`路径下,如果proxy_pass的路径为`/bbb/ccc`,那么实际请求的就是`bbb`路径下的`cccindex.html`)

  1. proxy_pass后面还有其他路径但是最后有 /, 匹配路径也有斜杠(/aaa/)
1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
...

location /aaa/ {
proxy_pass http://127.0.0.1:8081/bbb/;
proxy_rediect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}

此时通过浏览器访问:http://域名/aaa/index.html,实际访问的是http://127.0.0.1:8081/bbb/index.html

  1. location匹配路径末尾没有 /,proxy_pass后面也没有/
1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
...

location /aaa {
proxy_pass http://127.0.0.1:8081;
proxy_rediect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
...
}

此时访问http://域名/aaa,默认将请求到http://127.0.0.1:8081/aaa/index.html的内容

坚持原创技术分享,您的支持将鼓励我继续创作!
0%