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

11 KiB
Raw Blame History

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匹配上后,就跳到某一个页面去,或者被反向代理到另一个位置去 等等

更多的内容 我们在下篇中 再继续 ^_^