location目录匹配规则

nginx每个location都是一个匹配目录,
nginx的策略是:访问请求来时,会对访问地址进行解析,从上到下逐个匹配,检查是否有更具体的 location 块可以匹配这个请求,
匹配上就执行对应location大括号中的策略,并根据策略对请求作出相应。

举例:

location / {  
    root   /usr/share/nginx/html/;  
    index  index.html index.htm;  
    try_files $uri $uri/ /index.html last;  
}

location /dapingYdd {  
    root   /usr/share/nginx/html/;  
    index  index.html index.htm;  
    try_files $uri $uri/ /index.html last;  
}

当您发送一个请求 http://127.0.0.1:8081/dapingYdd 时,Nginx 会首先检查是否有更具体的 location 块可以匹配这个请求。
在这种情况下,location /dapingYdd 是一个更具体的匹配,因为它直接匹配了请求的 URI 开头部分。
第一个配置 location / 实际上是一个回退(fallback)配置,它会在没有更具体的 location 块匹配时才会被使用。
所以,对于 http://127.0.0.1:8081/dapingYdd 请求,它不会走第一个配置 location /,只会走第二个配置,即 location /dapingYdd。

location URI结尾带不带 /

(1)一般正常的情况下

首先要知道:Nginx 的默认行为一般会使不带尾斜杠的目录请求重定向到带尾斜杠的 URL(此处强调 为 nginx 行为)
根据约定,URL 尾部的 / 表示目录,没有 / 表示文件

  • 假设 请求的地址为 http://127.0.0.1:8081/dapingYdd/,
    服务器会自动去该目录下找对应的默认文件(index.html)

  • 假设 请求的地址为 http://127.0.0.1:8081/dapingYdd,
    服务器会先去找 dapingYdd 文件,找不到的话会将 some-dir 当成目录,重定向到 /dapingYdd/ ,去该目录下找默认文件(index.html)。

所以把nginx配置成以下这个,就可以实现不管输入的地址结尾是否带 /,都能正确的访问到你的网页

# 这个是ok的。
location /dapingYdd {  
    root   /usr/share/nginx/html/;  
    index  index.html index.htm;  
    try_files $uri $uri/ /index.html last;  
}

可千万不能写成

# 这个只能 支持 http://127.0.0.1:8081/dapingYdd/ 的请求,才能正确访问。
location /dapingYdd/ {  
    root   /usr/share/nginx/html/;  
    index  index.html index.htm;  
    try_files $uri $uri/ /index.html last;  
}

详细具体 请参考
十分钟,我们一起搞定nginx配置location带不带/

(2)无法自动重定向的情况下

如果在配置了以上的情况下。没有出现所谓的重定向,就可以需要我们自己手动去加配置

解决Nginx访问URL末尾不加斜杠 / 报404错误

前提是

如果配置/yyy后出现没有重定向,可能是版本问题,才需要我们自己手动去加配置

现象:
访问http://xxx.com/yyy/:会匹配到服务器的/zzz/aaa/yyy文件夹下index.html或index.htm。
访问http://xxx.com/yyy:会匹配失败报404错误。

操作方式

(1)既然加斜杠/可以匹配,那么可以对不加斜杠/的URL进行重写,末尾加上斜杠,然后重定向。
(2)首先判断请求资源是否为目录类型,然后利用正则匹配替换,进行重定向

server {
    listen 80
    server_name xxx.com
    ...
    location /yyy {
        root /zzz/aaa;
        ## 如果配置/yyy后出现没有重定向,可能是版本问题,就需要我们自己手动去加配置
        if (-d $request_filename){
            rewrite ^/(.*)([^/])$ $scheme://$host/$1$2/ permanent;
        }
        index index.html index.htm;
    }
    ...
}
#验证nginx.conf
./sbin/nginx -t
#重启Nginx
./sbin/nginx -s reload

h5包结构

一般为static文件夹+index.html文件

h5包代理配置之root

使用root时,访问的url是root定义的目录加上location匹配的路径

location /assets/ {
root /git/shortUrl/dist/;
}

访问 http://domain/assets/a.js 时, 
实际访问:http://domain/git/shortUrl/dist/assets/a.js

h5包代理配置之alias

使用alias时,访问的url直接是alias所定义的路径

location /assets/ {
alias /git/shortUrl/dist/;
}

访问 http://domain/assets/a.js 时,
实际访问:http://domain/git/shortUrl/dist/a.js

以下为总结配置
我这一块配置为了习惯统一化 不管前端还是接口配置 location后面都带上斜杠。

前端代理配置

我比较常用的为alias方式

# 演示root和alias两种配置静态资源的区别
  server {
    listen 80;
    server_name localhost;

    # 用root方式,location中的路径会拼加到root的地址后面
    # 请求路径为:http://localhost:8080/files/index.jpg    实际访问为:/home/files/index.jpg
    location ~^/files/ {
      root /home/;
      index index.html index.htm;
    }
    # 用alias方式,location中的路径不会拼加到alias的地址后面
    # 这请求路径为:http://localhost:8080/files/index.jpg    实际访问为:/home/index.jpg
    location ~^/files/ {
      alias /home/;
      index index.html index.htm;
    }
  }

以下是我配置的前端方式
会添加一行代码 try_files $uri $uri/ /index.html last;

##  web页面
        location /images/ {
		alias   /opt/html/ ;
		try_files $uri $uri/ /index.html last;
		#autoindex on;
		add_header Access-Control-Allow-Origin *;
		add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
		add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
	   }

比如 请求 127.0.0.1/images/test.gif 会依次查找
1.文件/opt/html/images/test.gif
2.文件夹 /opt/html/images/test.gif/下的index.html文件
3. 找不到,再请求/opt/html/index.html

因此,try_files $uri $uri/ /index.html last的意思是:

首先,查找当前请求的URI对应的文件。
如果找到了文件,则返回该文件。
如果没有找到文件,则查找当前请求的URI对应的目录。
如果找到了目录,则返回该目录下的索引文件(如index.html)。
如果还是没有找到文件,则返回/index.html。
如果还是没有找到文件,则将请求传递给下一个处理程序。
举个例子,假设当前请求的URI为/foo/bar,文档根目录为/var/www,则try_files $uri $uri/ /index.html last会按照以下顺序查找文件:

/var/www/foo/bar
/var/www/foo/bar/
/var/www/index.html
如果还是没有找到文件,则将请求传递给下一个处理程序
根据提供的引用内容,alias和 try_files $uri $uri/ /index.html last  是 Nginx 配置中的两个指令,它们的作用不同。

alias 的作用是将 URL 中的某一部分映射到服务器上的某个目录或文件。例如,如果我们有一个 URL /static/image.jpg,我们可以使用 alias 将其映射到服务器上的 /var/www/static/image.jpg 文件。alias 的语法是 alias path,其中 path 是服务器上的目录或文件路径。

try_files $uri $uri/ /index.html 的作用是在 Nginx 服务器上配置 Vue.js 单页应用程序,使得当 URL 发生变化时,页面不会重新加载,而是通过 URL 的 hash 值来模拟一个完整的 URL。这个指令的意思是,首先尝试访问 $uri 对应的文件或目录,如果找不到,则尝试访问 $uri/ 对应的目录,如果还是找不到,则返回 /index.html 对应的文件。

因此,alias 和 try_files $uri $uri/ /index.html last 没有直接的关系,它们是用于不同的场景和目的的 Nginx 指令。

后端代理配置

以下这种方式我用的比较多

# 请求路径为:http://127.0.0.1:8080/api/getUser   实际代理为:http://127.0.0.1:8000/getUser
    location ^~/api/ {
      proxy_pass http://127.0.0.1:8000/;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }

Nginx之正则表达式

(1)location = / {}
=为精确匹配 / ,主机名后面不能带任何字符串,比如访问 / 和 /data,则 / 匹配,/data 不匹配
再比如 location = /abc,则只匹配/abc ,/abc/或 /abcd不匹配。若 location  /abc,则即匹配/abc 、/abcd/ 同时也匹配 /abc/。
 
(2)location / {}
因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求 比如访问 / 和 /data, 则 / 匹配, /data 也匹配,
但若后面是正则表达式会和最长字符串优先匹配(最长匹配)
 
(3)location /documents/ {}
匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
 
(4)location /documents/abc {}
匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索其它 location
只有其它 location后面的正则表达式没有匹配到时,才会采用这一条
 
(5)location ^~ /images/ {}
匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条
 
(6)location ~* \.(gif|jpg|jpeg)$ {}
匹配所有以 gif、jpg或jpeg 结尾的请求
然而,所有请求 /images/ 下的图片会被 location ^~ /images/ 处理,因为 ^~ 的优先级更高,所以到达不了这一条正则
 
(7)location /images/abc {}
最长字符匹配到 /images/abc,优先级最低,继续往下搜索其它 location,会发现 ^~ 和 ~ 存在
 
(8)location ~ /images/abc {}
匹配以/images/abc 开头的,优先级次之,只有去掉 location ^~ /images/ 才会采用这一条
 
(9)location /images/abc/1.html {}
匹配/images/abc/1.html 文件,如果和正则 ~ /images/abc/1.html 相比,正则优先级更高

参考的相关的其他配置方式

相关链接

# 进程数量
worker_processes 1;

events {
  # 最大连接数量
  worker_connections 1024;
}

http {
  include mime.types;
  default_type application/octet-stream;
  sendfile on;
  keepalive_timeout 65;

  # 演示如何强制http跳转https
  server {
    listen 80;
    server_name test.com;

    # http强制跳转到https
    rewrite ^(.*)$ https://$server_name$1 permanent;
  }

  # 演示如何配置微信支付的校验文件
  server {
    listen 80;
    server_name localhost;

    # 默认根路径
    location / {
      root index.html;
    }
    # 微信支付校验文件,可以直接配置访问名称
    location ^~/MP_verify_2g3uEjrB5B2LIbNl.txt {
      alias /home/MP_verify_2g3uEjrB5B2LIbNl.txt;
    }
    # 微信支付校验文件,也可以通过正则配置
    location ~^/MP_verify_[a-zA-Z0-9]*\.(txt)$ {
      root /home/;
      rewrite ^/home/(.txt)$ /home/$1 last;
    }
  }

  # 演示root和alias两种配置静态资源的区别
  server {
    listen 80;
    server_name localhost;

    # 用root方式,location中的路径会拼加到root的地址后面
    # 请求路径为:http://localhost:8080/files/index.jpg    实际访问为:/home/files/index.jpg
    location ~^/files/ {
      root /home/;
      index index.html index.htm;
    }
    # 用alias方式,location中的路径不会拼加到alias的地址后面
    # 这请求路径为:http://localhost:8080/files/index.jpg    实际访问为:/home/index.jpg
    location ~^/files/ {
      alias /home/;
      index index.html index.htm;
    }
  }

  # 演示请求后台接口代理配置
  server {
    listen 8080;
    server_name localhost;

    #################### 第一种场景(代理地址不加斜杠) ####################
    # 请求路径为:http://127.0.0.1:8080/api/getUser 
    # 实际代理为:http://127.0.0.1:8000/api/getUser
    location ^~/api/ {
      proxy_pass http://127.0.0.1:8000;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }
    # 请求路径为:http://127.0.0.1:8080/api/getUser   
    # 实际指向为:http://127.0.0.1:8000/api/getUser
    location ^~/api {
      proxy_pass http://127.0.0.1:8000;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }

    #################### 第二种场景(代理地址+斜杠) ####################
    # 请求路径为:http://127.0.0.1:8080/api/getUser
    #  实际代理为:http://127.0.0.1:8000/getUser
    location ^~/api/ {
      proxy_pass http://127.0.0.1:8000/;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }
    # 请求路径为:http://127.0.0.1:8080/api/getUser  
    # 实际代理为:http://127.0.0.1:8000//getUser
    location ^~/api {
      proxy_pass http://127.0.0.1:8000/;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }

    #################### 第三种场景(代理地址+后缀) ####################
    # 请求路径为:http://127.0.0.1:8080/api/getUser   
    # 实际代理为:http://127.0.0.1:8000/user/getUser
    location ^~/api {
      proxy_pass http://127.0.0.1:8000/user;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }
    # 请求路径为:http://127.0.0.1:8080/api/getUser  
    # 实际代理为:http://127.0.0.1:8000/usergetUser
    location ^~/api/ {
      proxy_pass http://127.0.0.1:8000/user;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }

    #################### 第四种场景(代理地址+后缀+斜杠) ####################
    # 请求路径为:http://127.0.0.1:8080/api/getUser   
    # 实际代理为:http://127.0.0.1:8000/user/getUser
    location ^~/api/ {
      proxy_pass http://127.0.0.1:8000/user/;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }
    # 请求路径为:http://127.0.0.1:8080/api/getUser  
    # 实际代理为:http://127.0.0.1:8000/user//getUser
    location ^~/api {
      proxy_pass http://127.0.0.1:8000/user/;
      proxy_set_header Host $http_host; #后台可以获取到完整的ip+端口号
      proxy_set_header X-Real-IP $remote_addr; #后台可以获取到用户访问的真实ip地址
    }
  }

  # 演示前端项目如何部署nginx
  server {
    listen 8090;
    server_name localhost;

	# 默认访问
    # 部署路径:/home/web/my_demo
    # 访问路径为:http://localhost:8090/
    location / {
      try_files $uri $uri/ /index.html;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $http_host;
      root /home/web/my_demo/;
      index index.html index.htm;
    }

	# 带前缀的访问
    # 部署路径:/home/web/my_demo
    # 访问路径为:http://localhost:8090/my_demo/
    # 如果location路径最后没有配置斜杠,则浏览器输入访问地址后,路径最后会自动拼一个斜杠
    location ^~/my_demo/ {
      try_files $uri $uri/ /my_demo/index.html;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $http_host;
      root /home/web/;
      index index.html index.htm;
    }
  }
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐