Files
baim0-learn/nginx/07.认识Nginx中的location和正则表达式,一起啃这块硬骨头(上篇).md
T
2024-03-12 08:29:44 +08:00

340 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 7.认识Nginx中的location和正则表达式,一起啃这块硬骨头(上篇)
【初识location阶段】
Nginx的location,我们在上一个篇幅中 跟大家提过,确实很不好理解 是不是还是心有余悸呢 (会者不难 不用太担心)
记不记得 我们之前讲过,nginx处理一个请求的时候,都是按用户输入的URL为基准,然后从左至右的来处理的
如果拆开来看一个URL 是这样的
([http://nginx.org:80/static/](http://nginx.org/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;
```plain
location / {
proxy_pass http://html/index.html;
access_log /var/log/nginx/access_html.log html_log;
}
}
```
上面这段配置中,用户URL输入的 域名和端口 被server{}模块自身就匹配并处理了
而域名和端口匹配上之后,接下来 就是以一个 最右边结尾的 '/' 作为分隔符,再往右的部分 我们称作 "路径"
那么 这个"路径"的匹配 ,就只能交给谁来做呢? 自然就是location{}啦 :)
location的作用 就是用来判断 用户在URL中 输入的"路径"的不同,然后再给导向到不同页面或者位置
(一个网站 总不能仅仅存在一个首页吧,总还得有其他的分页面吧,不然谁还会去浏览呢? 所以 就是有了路径区分页面,而相对的也就有了 处理路径的 location )
接下来 我们先把nginx配置成如下这个样子
```plain
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
而理解的难点,在于中间的 匹配符号这里 ,因为说实在的 这里只能靠死记硬背 并没有什么规则可循
我们接下来 还是直接通过 例子 和 实验 来学习吧
首先 咱们看第一项
```plain
location / {
return 201;
}
```
这一项 代表默认匹配 ,这样的写法就是说 如果其他的location全都匹配不上的时候,就回来找这一项来匹配
所以说 这个默认匹配的优先级是最低的 ,但分后面有一项能匹配上 也不会回来找它 ,除非是乱输入
接下来 我们就来试一试
用如下的方法 curl -I 查看返回码的方式来进行测试
\[root@server01 ~\]# curl -I [http://dami01.example.com/sdfsdfsdfsdfsdf](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://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是怎么自己设置的 为了观察)
好的 接下来 咱们看第一项和第二项和第三项在一起的情况
```plain
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://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 一模一样 ,多一个别的字符都没有
```plain
location = /nginx {
return 202;
}
```
一旦被 这个location的精确匹配抓到了,那么后面的 返回203的location 即便匹配上了 也没用了
接下来 咱们再换一种 输入方式
\[root@server01 ~\]# curl -I [http://dami01.example.com/nginx/](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://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抓到了
```plain
location /nginx {
return 203;
}
```
为什么第二项location(返回202的) 抓不到了呢?
因为 这两次 咱们的输入 是 /nginx/ 和 /nginxsdasdf , 而 location = /nginx 可是眼睛里不揉沙子哦 必须输入的一模一样 多一个少一个字符都不行
而第三项 location /nginx 这个就相对宽松太多了, 它的意思是 只要用户输入的路径以 /nginx起始就行,后面的部分 随便输入什么 都无所谓 都可以匹配上
所以说 /nginx/ 和 /nginxsdasdf 这样的输入,都是满足了 前面以"/nginx"开头,后面再随意的输入
好的 接下来 咱们看 第四项和第五项规则
```plain
location ~ /Nginx/$ {
return 204;
}
location ~* /nginx/$ {
return 205;
```
先做一个简单的说明吧
location ~ 代表的是 区分大小写的正则表达式
location ~\* 代表的是 不区分大小写的正则表达式
204这一项代表的是,用户输入的nginx 必须开头字母大写,而且最后还必须是 '/'结尾 才能匹配上
($意思是 以某个字符结尾, /$ :以'/' 结尾)
而205这一项 代表的是 不区分大小写,但也得以 / 结尾
接下来咱们做实验吧
\[root@server01 ~\]# curl -I [http://dami01.example.com/Nginx/](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://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://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匹配到
再加入一项
```plain
location ~ \.jpg$ {
return 207;
}
```
这种代表的是 以.jpg结尾 我们当前的配置是
```plain
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://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://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://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匹配上后,就跳到某一个页面去,或者被反向代理到另一个位置去 等等
更多的内容 我们在下篇中 再继续 ^\_^