Nginx location的使用

  • Nginx是什么

Nginx(发音同engine x)是一个异步框架的 Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存。
也有人这么解释
nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;
同时也是一个IMAP、POP3、SMTP代理服务器;
nginx可以作为一个HTTP服务器进行网站的发布处理,
另外nginx可以作为反向代理进行负载均衡的实现。

  • nginx.conf的目录结构

整个conf文件分为** 全局块、events块、http块、server块、location块**。每个块有每个块的作用域,越外层的块作用域就包含内部块的作用域,如全局块作用域就包含events块、http块、server块和location块。

                    #全局块

event{              #events块
    ...
}

http{               #http块

    server{         #server块
        ...         #server全局块

        location{   #location块
            ...
        }

        location{   #location块
            ...
        }
    }

    server{         #server块
        ...
    }
    ...             #http全局块
}
  • http块

http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这模块中。作用包括:文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。

  • server块

server块,虚拟主机(虚拟服务器)。作用:使得Nginx服务器可以在同一台服务器上至运行一组Nginx进程,就可以运行多个网站。

  • location块

location块是server块的一个指令。作用:基于Nginx服务器接收到的请求字符串,虚拟主机名称(ip,域名)、url匹配,对特定请求进行处理。

location 说明

  • location语法
location [=|~|~*|^~|@] /uri/ { … } ,意思是可以以“ = ”或“ ~* ”或“ ~ ”或“ ^~ ”或“ @ ”符号为前缀,
当然也可以没有前缀(因为 [A] 是表示可选的 A ; A|B 表示 A 和 B 选一个),紧接着是 /uri/ ,
再接着是{…} 指令块,整个意思是对于满足这样条件的 /uri/ 适用指令块 {…} 的指令。
  • location的分类

location分为两类,一类为普通 location,一类为正则location。

  1. 普通location
“普通 location ”是以“ = ”或“ ^~ ”为前缀或者没有任何前缀的 /uri/ 
  1. 正则location
“正则 location ”是以“ ~ ”或“ ~* ”为前缀的 /uri/
  • 多个location场景下的location匹配

Nginx 的 location 匹配规则是:“正则 location ”让步 “普通 location”的严格精确匹配结果;但覆盖 “普通 location ”的最大前缀匹配结果。

  • 例子1 先普通location,再正则location匹配
server {
     
      listen       9090;
      server_name  localhost;
          location / {
     
          root   html;
          index  index.html index.htm;
          deny all;
      }
      location ~ \.html$ {
     
          allow all;
      }
}

location / {… deny all;} 普通 location 以“ / ”开始的 URI 请求(注意任何 HTTP 请求都必然以“/ ”开始,所以“ / ”的意思是所有的请求都能被匹配上),都拒绝访问; location ~.html$ {allow all;} 正则 location以 .html 结尾的 URI 请求,都允许访问。

  • 测试结果
[root@web108 ~]# curl http://localhost:9090/
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor=”white”>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.1.0</center>
</body>
</html>
[root@web108 ~]# curl http://localhost:9090/index.html
<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body bgcolor=”white” text=”black”>
<center><h1>Welcome to nginx!</h1></center>
</body>
</html>
[root@web108 ~]# curl http://localhost:9090/index_notfound.html
<html>
<head><title>404 Not Found</title></head>
<body bgcolor=”white”>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.1.0</center>
</body>
</html>
  • curl http://localhost:9090/ 的结果是“ 403 Forbidden ”,说明被匹配到“ location / {…deny all;} ”了,原因很简单HTTP 请求 GET / 被“严格精确”匹配到了普通 location / {} ,则会停止搜索正则 location ;
  • curl http://localhost:9090/index.html 结果是“ Welcome to nginx! ”,说明没有被“ location / {…deny all;} ”匹配,否则会 403 Forbidden ,但 /index.html 的确也是以“ / ”开头的,只不过此时的普通 location / 的匹配结果是“最大前缀”匹配,所以 Nginx 会继续搜索正则 location , location ~ .html$ 表达了以 .html 结尾的都 allow all; 于是接着就访问到了实际存在的 index.html 页面。
  • curl http://localhost:9090/index_notfound.html 同样的道理先匹配 location / {} ,但属于“普通 location 的最大前缀匹配”,于是后面被“正则 location ” location ~ .html$ {} 覆盖了,最终 allow all ; 但的确目录下不存在index_notfound.html 页面,于是 404 Not Found 。
  • 如果此时我们访问 http://localhost:9090/index.txt 会是什么结果呢?显然是 deny all ;因为先匹配上了 location / {…deny all;} 尽管属于“普通 location ”的最大前缀匹配结果,继续搜索正则 location ,但是 /index.txt 不是以 .html结尾的,正则 location 失败,最终采纳普通 location 的最大前缀匹配结果,于是 deny all 了。
  • 例子2 普通 location 的“隐式”严格匹配
//在例子1的基础上增加精确匹配
server {
     
       listen       9090;
       server_name  localhost;
        location /exact/match.html {
     
           allow all;
       }
           location / {
     
           root   html;
           index  index.html index.htm;
           deny all;
       }
       location ~ \.html$ {
     
           allow all;
       }
}
  • 测试结果
[root@web108 ~]# curl http://localhost:9090/exact/match.html

404 Not Found

404 Not Found


nginx/1.1.0

结果进一步验证了“普通 location ”的“严格精确”匹配会终止对正则 location 的搜索。这里我们小结下“普通 location”与“正则 location ”的匹配规则:先匹配普通 location ,再匹配正则 location ,但是如果普通 location 的匹配结果恰好是“严格精确( exact match )”的,则 nginx 不再尝试后面的正则 location ;如果普通 location 的匹配结果是“最大前缀”,则正则 location 的匹配覆盖普通 location 的匹配。也就是前面说的“正则 location 让步普通location 的严格精确匹配结果,但覆盖普通 location 的最大前缀匹配结果”。

  • 普通 location 的“显式”严格匹配和“ ^~ ” 前缀

上面我们演示的普通 location 都是不加任何前缀的,其实普通 location 也可以加前缀:“ ^~ ”和“ = ”。其中“ ^~”的意思是“非正则,不需要继续正则匹配”,也就是通常我们的普通 location ,还会继续搜索正则 location (恰好严格精确匹配除外),但是 nginx 很人性化允许配置人员告诉 nginx 某条普通 location ,无论最大前缀匹配,还是严格精确匹配都终止继续搜索正则 location ;而“ = ”则表达的是普通 location 不允许“最大前缀”匹配结果,必须严格等于,严格精确匹配。

  • 例子3
server {
       listen       9090;
       server_name  localhost;
          location /exact/match.html {
           allow all;
       }
           location ^~ / {
           root   html;
           index  index.html index.htm;
           deny all;
       }
       location ~ \.html$ {
           allow all;
       }
}
  • 测试
curl http://localhost:9090/	403 Forbidden	403 Forbidden
curl http://localhost:9090/index.html	Welcome to nginx!	403 Forbidden
curl http://localhost:9090/index_notfound.html	404 Not Found	403 Forbidden
curl http://localhost:9090/exact/match.html	404 Not Found	404 Not Found
  • 正则 location 与编辑顺序

location 的指令与编辑顺序无关,这句话不全对。对于普通 location 指令,匹配规则是:最大前缀匹配(与顺序无关),如果恰好是严格精确匹配结果或者加有前缀“ ^~ ”或“ = ”(符号“ = ”只能严格匹配,不能前缀匹配),则停止搜索正则 location ;但对于正则 location 的匹配规则是:按编辑顺序逐个匹配(与顺序有关),只要匹配上,就立即停止后面的搜索。

server {
     
       listen       9090;
       server_name  localhost;
       location ~ \.html$ {
     
           allow all; 
       }  
       location ~ ^/prefix/.*\.html$ {
     
           deny all;  
       }  
}
server {
     
       listen       9090;
       server_name  localhost;
       location ~ ^/prefix/.*\.html$ {
     
           deny all;  
       }  
        location ~ \.html$ {
     
           allow all; 
       } 
}
  • 测试结果
curl http://localhost:9090/regextest.html	404 Not Found	404 Not Found
curl http://localhost:9090/prefix/regextest.html	404 Not Found	403 Forbidden
Location ~ ^/prefix/.*\.html$ {
     deny all;} 表示正则 location 对于以 /prefix/ 开头,
 .html 结尾的所有 URI 请求,都拒绝访问;   location ~\.html${
     allow all;} 
 表示正则 location 对于以 .html 结尾的 URI 请求,都允许访问。 实际上,
 prefix 的是 ~\.html$ 的子集。在“配置 3.1 ”下,两个请求都匹配上 location ~\.html$ {
     allow all;} ,
 并且停止后面的搜索,于是都允许访问, 404 Not Found ;在“配置 3.2 ”下, /regextest.html 无法匹配 prefix ,
 于是继续搜索 ~\.html$ ,允许访问,于是 404 Not Found ;然而 /prefix/regextest.html 匹配到 prefix ,
 于是 deny all , 403 Forbidden 。

参考文章

[^1 ]关于一些对location认识的误区

你可能感兴趣的:(Nginx,Nginx,location)