11 KiB
7.认识Nginx中的location和正则表达式,一起啃这块硬骨头(上篇)
【初识location阶段】
Nginx的location,我们在上一个篇幅中 跟大家提过,确实很不好理解 是不是还是心有余悸呢 (会者不难 不用太担心)
记不记得 我们之前讲过,nginx处理一个请求的时候,都是按用户输入的URL为基准,然后从左至右的来处理的
如果拆开来看一个URL 是这样的
(http://nginx.org:80/static/)
-> http:// -> nginx.org -> :80 -> /static/
URL按照顺序被拆分开来后,相应的 nginx也会调用不同的模块和子模块 来进行处理
大体按照如下这样的顺序
http{}模块 -> server{}模块 -> location模块
下面咱们 通过之前的一段配置来一起看一下 会更明白一些
server {
listen 80;
server_name html.example.com;
access_log /var/log/nginx/access_html2.log html_log;
location / {
proxy_pass http://html/index.html;
access_log /var/log/nginx/access_html.log html_log;
}
}
上面这段配置中,用户URL输入的 域名和端口 被server{}模块自身就匹配并处理了
而域名和端口匹配上之后,接下来 就是以一个 最右边结尾的 '/' 作为分隔符,再往右的部分 我们称作 "路径"
那么 这个"路径"的匹配 ,就只能交给谁来做呢? 自然就是location{}啦 :)
location的作用 就是用来判断 用户在URL中 输入的"路径"的不同,然后再给导向到不同页面或者位置
(一个网站 总不能仅仅存在一个首页吧,总还得有其他的分页面吧,不然谁还会去浏览呢? 所以 就是有了路径区分页面,而相对的也就有了 处理路径的 location )
接下来 我们先把nginx配置成如下这个样子
server {
listen 80;
server_name dami01.example.com;
location / {
return 201;
}
location = /nginx {
return 202;
}
location /nginx {
return 203;
}
location ~ /Nginx {
return 204;
}
location ~* /nginx {
return 205;
}
location ~ \.jpg$ {
return 206;
}
location ~ /login/ {
root /var/www/html/vhost/dami01.example.com/;
}
}
先简单解释一下 上面这一段的配置文件
可以看到server下 有很多个location并列的放在一起 每一个location表示一种匹配的方法
另外,location中 我们调用了 return 2xx, 这个是代表 一旦匹配上了 就给予不同的返回值
(不同的返回值的目的 就为了让我们在测试的时候 一目了然 知道自己的输入被哪一项location匹配上了 ok? )
那么location到底是通过什么方式 来匹配用户的输入呢?
- 简单的说 就是location的写法 分成三个部分
-
location关键字 + 匹配符号 + 路径字段
例如: location + = + /nginx
而理解的难点,在于中间的 匹配符号这里 ,因为说实在的 这里只能靠死记硬背 并没有什么规则可循
我们接下来 还是直接通过 例子 和 实验 来学习吧
首先 咱们看第一项
location / {
return 201;
}
这一项 代表默认匹配 ,这样的写法就是说 如果其他的location全都匹配不上的时候,就回来找这一项来匹配
所以说 这个默认匹配的优先级是最低的 ,但分后面有一项能匹配上 也不会回来找它 ,除非是乱输入
接下来 我们就来试一试
用如下的方法 curl -I 查看返回码的方式来进行测试
[root@server01 ~]# curl -I http://dami01.example.com/sdfsdfsdfsdfsdf
HTTP/1.1 201 Created
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 04:57:30 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
[root@server01 ~]# curl -I http://dami01.example.com/hahaha
HTTP/1.1 201 Created
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 04:57:34 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
看到了没? 测试的时候 即便胡乱的输入URL(胡乱输入URL的路径 那肯定别的location都匹配不上了),最终都会匹配到 咱们的第一项默认location
因为 location / 指的是,只要你路径中以 / 开头了 不管你后面输入啥 都能匹配到(路径无论如何 都会以 / 起头)。于是返回201 (201是怎么自己设置的 为了观察)
好的 接下来 咱们看第一项和第二项和第三项在一起的情况
location / {
return 201;
}
location = /nginx {
return 202;
}
location /nginx {
return 203;
}
第二项这个 location = /nginx , 这里需要重点给大家强调一下了
单独一个 = 号, 代表的是 最高优先级+精准匹配 !!
什么意思呢? 首先最高优先级 意思是说,只要用户输入的URL 能匹配上这一条,那么其他的location一律全忽略掉(就算其他的也可以匹配上 都不管了) 只调用这里的
精准匹配 是什么意思呢? 就是 一点都不能差!
也就是说,= 后面写的内容 和 用户输入的路径 必须完全完全一模一样 ,稍有变化 则匹配不上了
接下来 咱们做实验吧
我们按照如下 这样输入URL, 返回202
[root@server01 ~]# curl -I http://dami01.example.com/nginx
HTTP/1.1 202 Accepted
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:06:13 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
返回202 说明被下面的location 匹配上了,而且是精准匹配 ,因为 用户输入的 /nginx 和 location = 后面的 /nginx 一模一样 ,多一个别的字符都没有
location = /nginx {
return 202;
}
一旦被 这个location的精确匹配抓到了,那么后面的 返回203的location 即便匹配上了 也没用了
接下来 咱们再换一种 输入方式
[root@server01 ~]# curl -I http://dami01.example.com/nginx/
HTTP/1.1 203
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:09:32 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
[root@server01 ~]#
[root@server01 ~]# curl -I http://dami01.example.com/nginxsdfasdf
HTTP/1.1 203
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:09:39 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
注意 这次输入的URL有变化了, 第一个是 /nginx/ 第二个是 /nginxsdasdf
首先 ,这两次的输入 返回203 是被如下第三项location抓到了
location /nginx {
return 203;
}
为什么第二项location(返回202的) 抓不到了呢?
因为 这两次 咱们的输入 是 /nginx/ 和 /nginxsdasdf , 而 location = /nginx 可是眼睛里不揉沙子哦 必须输入的一模一样 多一个少一个字符都不行
而第三项 location /nginx 这个就相对宽松太多了, 它的意思是 只要用户输入的路径以 /nginx起始就行,后面的部分 随便输入什么 都无所谓 都可以匹配上
所以说 /nginx/ 和 /nginxsdasdf 这样的输入,都是满足了 前面以"/nginx"开头,后面再随意的输入
好的 接下来 咱们看 第四项和第五项规则
location ~ /Nginx/$ {
return 204;
}
location ~* /nginx/$ {
return 205;
先做一个简单的说明吧
location ~ 代表的是 区分大小写的正则表达式
location ~* 代表的是 不区分大小写的正则表达式
204这一项代表的是,用户输入的nginx 必须开头字母大写,而且最后还必须是 '/'结尾 才能匹配上
(意思是 以某个字符结尾, / :以'/' 结尾)
而205这一项 代表的是 不区分大小写,但也得以 / 结尾
接下来咱们做实验吧
[root@server01 ~]# curl -I http://dami01.example.com/Nginx/
HTTP/1.1 204 No Content
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:27:07 GMT
Connection: keep-alive
[root@server01 ~]# curl -I http://dami01.example.com/NgiNx/
HTTP/1.1 205
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:27:18 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
[root@server01 ~]# curl -I http://dami01.example.com/ngiNx/
HTTP/1.1 205
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:27:25 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
第一次的测试,因为咱们完全符合了 204的规则,开头N大写,并且以/结尾 ,所以被204 location匹配抓到
后面的两次测试,由于我们没有遵守大小写的规定,但是依然是 nginx这个词,并且以/结尾,所以205location匹配到
再加入一项
location ~ \.jpg$ {
return 207;
}
这种代表的是 以.jpg结尾 我们当前的配置是
location / {
return 201;
}
location = /nginx {
return 202;
}
location /nginx {
return 203;
}
location ~ /Nginx/$ {
return 204;
}
location ~* /nginx/ {
return 205;
}
location ~ \.jpg$ {
return 206;
}
接下来 咱们来做实验吧
[root@server01 ~]# curl -I http://dami01.example.com/1.jpg
HTTP/1.1 206 Partial Content
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:40:43 GMT
Content-Type: image/jpeg
Content-Length: 0
Connection: keep-alive
[root@server01 ~]# curl -I http://dami01.example.com/abc.jpg
HTTP/1.1 206 Partial Content
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:40:45 GMT
Content-Type: image/jpeg
Content-Length: 0
Connection: keep-alive
[root@server01 ~]#
[root@server01 ~]# curl -I http://dami01.example.com/nginx/1.jpg
HTTP/1.1 205
Server: nginx/1.14.1
Date: Sat, 05 Jan 2019 05:40:51 GMT
Content-Type: image/jpeg
Content-Length: 0
Connection: keep-alive
从上面 咱们可以看出,不管路径怎么随便输入,只要咱们的URL中 出现了以 '.jpg'结尾,就可以被206匹配到
但是注意最后一次的 当咱们的URL是 /nginx/1.jgp的时候, 返回的是205了
这就说明 ~* /nginx/ 被匹配上了 并且 优先级 还比 ~ .jpg 高 ,所以 206被忽略了
大家私下里 就可以使用这种 location + return的方法 快速的自己测试 各种location匹配的方法 以及优先级
除此之外, location{} 括号之中的内容 ,可以单独定义 root , 也可以单独定义 proxy_pass
比如,被某一个location匹配上后,就跳到某一个页面去,或者被反向代理到另一个位置去 等等
更多的内容 我们在下篇中 再继续 ^_^