Location匹配

#Location #Host #Linux

匹配类型

修饰符 含义 示例
= 精确匹配 location = /api
^~ 前缀匹配,匹配到就停止 location ^~ /static/
~ 正则匹配(区分大小写) location ~ \.php$
~* 正则匹配(不区分大小写) `location ~* .(jpg|gif|png)$
普通前缀匹配 location /api/

  • 精确匹配

    location = /api {
     #.....
    }
    只有访问是 example.com/api 时才匹配
    example.com/api/ 
    example.com/apis 
    
  • 前缀匹配

    location ^~ /api/ {
     #....
    }
    example.com/api/ 
    example.com/apis 
    example.com/api/123456 
    
  • 正则匹配

    location ~*  \.(jpg|gif|png)$ { #\. 是转义 $表示结束
    
    }
    example.com/avatar.jpg 
    exampl.com/logo.svg 
    example.com/logo.pngDoSomeDangerAction 
    example.com/thepath/logo.png 
    

优先级

高  ┌─────────────────────┐
    │  =   精确匹配       │
    ├─────────────────────┤
    │  ^~  前缀匹配停止   │
    ├─────────────────────┤
    │  ~   正则(顺序)   │
    │  ~*  正则(顺序)   │
    ├─────────────────────┤
    │  无  最长前缀匹配   │
低  └─────────────────────┘

拼接规则

root & index

root 表示文件路径地址的根目录, index 表示当发送的请求是目录时会去该目录下查找的文件;

index 指令定义了当用户请求一个目录(而不是一个具体文件)时,Nginx 应该默认返回哪个文件;

location / {
 root /var/www/home/;
 index index.html index.htm index.php
}

当进入的请求是 example.com/ 时 会匹配到上述 location 匹配段 拆下来 / ,root + / = var/www/home/ 因为查找的是 dir 而非 file ,所以根据 index 从前往后查找 对应文件 / + index [1] = /index.html 重新在 conf 里匹配 。

因为 /index.html 符合 / 的规则,于是 root + /index.html, 此时访问的是具体的文件,检查是否存在然后返回。


alias

alias 常为改善 root 可能导致的 路径重复问题 而使用。

location /images/ {
	root /var/www/assets/pics/;
	
}

我们请求访问时如果是 example.com/images/img.png 到这里会被拆解拼接 /var/www/assets/pics/images/img.png

但我们实际只是 暴露给用户的地址是 images 我们的图片路径并不在这里,此时为了保证 API 的易读性和我们后端资源的有序我们可以使用 alias

location /images/ {
	alias /var/www/assets/pics/;
	
}

拼接结果就是 /var/www/assets/pics/img.png


巨坑

使用精准匹配导致 无法托管正确页面

如果我们用精准匹配去设置 根目录为欢迎页,会出错

location =/ {
 root /var/www/home/;
 index index.html index.htm index.php
}

1977/12/15 15:45:24 [debug] 332923#332923: *17 http request line: "GET / HTTP/1.1"
1977/12/15 15:45:24 [debug] 332923#332923: *17 http uri: "/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 http args: ""
1977/12/15 15:45:24 [debug] 332923#332923: *17 http exten: ""
1977/12/15 15:45:24 [debug] 332923#332923: *17 http header: "Accept: */*"
1977/12/15 15:45:24 [debug] 332923#332923: *17 http header done
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/avatar/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/404.html"
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 using configuration "=/"    #使用“=/精准匹配”
1977/12/15 15:45:24 [debug] 332923#332923: *17 open index "/var/www/home/index.html" #检查index.html是否存在
1977/12/15 15:45:24 [debug] 332923#332923: *17 internal redirect: "/index.html?" #内部重定向
1977/12/15 15:45:24 [debug] 332923#332923: *17 rewrite phase: 1
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/avatar/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/static/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/health" #找不到了因为 /index.html 不匹配 /
1977/12/15 15:45:24 [error] 332923#332923: *17 open() "/etc/nginx/html/index.html" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", host: "localhost:8070" 
1977/12/15 15:45:24 [debug] 332923#332923: *17 http finalize request: 404, "/index.html?" a:1, c:2
1977/12/15 15:45:24 [debug] 332923#332923: *17 http special response: 404, "/index.html?"
1977/12/15 15:45:24 [debug] 332923#332923: *17 internal redirect: "/404.html?"
1977/12/15 15:45:24 [debug] 332923#332923: *17 rewrite phase: 1
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/avatar/"
1977/12/15 15:45:24 [debug] 332923#332923: *17 test location: "/404.html"
1977/12/15 15:45:24 [debug] 332923#332923: *17 using configuration "=/404.html"

解决方案

  1. 使用 try_files

    try_files 检查文件是否按指定顺序存在,并使用 第一个用于请求处理的寻得文件; 处理过程 在当前语境下执行。

    Checks the existence of files in the specified order and uses the first found file for request processing;

    这样就避免了内部重定向

    location =/ {
     root /var/www/home/;
     try_files /index.html =404 
    }
    
  2. 将 root 放在全局

admin/ 与 admin 同时跳转同一 index

location /admin {
	alias /var/www/admin/;
	index index.html;
	try_files $uri $uri/index.html =404;
}

Reference

title: "Nginx基础知识从小白到入门"
image: "https://raw.githubusercontent.com/wsgzao/storage-public/master/img/20191113180648.png"
description: "Nginx基础知识从小白到入门"
url: "https://wsgzao.github.io/post/nginx/"
favicon: ""
aspectRatio: "96.79245283018868"
title: "Nginx 快速教程"
image: "https://raw.githubusercontent.com/dunwu/images/master/cs/web/nginx/nginx.jpg"
description: "nginx-tutorial"
url: "https://dunwu.github.io/nginx-tutorial/#/nginx-quickstart"
favicon: ""
aspectRatio: "56.26959247648903"
title: "Nginx 从入门到实践(2023年版)Nginx 简介 Nginx 是什么 nginx (engine x) 是一个  - 掘金"
image: "https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/75209bc63f284481ae19c0c98d41187e~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp?"
description: "Nginx 简介 Nginx 是什么 nginx (engine x) 是一个 HTTP 和反向代理服务器,一个邮件代理服务器,一个通用的 TCP/UDP 代理服务器,最初由 Igor Sysoev "
url: "https://juejin.cn/post/7223653286464667703#heading-20"
favicon: ""
aspectRatio: "96.18268575323789"
title: "try_files 文档"
image: "https://nginx.org/img/nginx_logo.svg"
description: ""
url: "https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files"
favicon: ""
aspectRatio: "28.666666666666668"
title: "index 文档"
image: "https://nginx.org/img/nginx_logo.svg"
description: ""
url: "https://nginx.org/en/docs/http/ngx_http_index_module.html#index"
favicon: ""
aspectRatio: "28.666666666666668"