Nginx index转发导致首页无法访问

这两天在部署短链接服务,配置 nginx 规则卡了一晚上,特此记录一下。

Nginx 配置及现象

我的需求是如果访问域名,那么直接展示首页,如果访问其他路径,则转发到后端服务。conf.d/default.conf 文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
server {
listen 80;
listen [::]:80;
server_name localhost;

#access_log /var/log/nginx/host.access.log main;

location = / {
root /usr/share/nginx/html;
index index.html;
}

location / {
proxy_pass http://192.168.0.10:8000;
}

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

}

根据 nginx 中 = 精确匹配的优先级最好的原则,直接访问域名会匹配到第一个规则。但是实际上请求还是会被转发到后端,非常困惑。

途中发现一个很好用的 nginx 规则验证工具:Nginx location match tester 。每次修改规则之后要重启,再发起请求然后看结果来验证配置是否符合预期,非常繁琐,这个工具网站可以省去这些步骤,极大的提高效率。

问题和解决方案

今天上午认真的读了一篇写得挺不错的 nginx 配置教程:一文理清 nginx 中的 location 配置(系列一),在文章下的评论中看到有人贴出了自己遇到的问题,配置以及问题描述都和我遇到的问题一致,原来是 index 转发的问题。

如下配置,访问网站根目录并没有正常显示,而是返回了 404:

1
2
3
4
5
6
7
location = / {
index index.html;
}

location / {
return 404;
}

苏凡@诚先森 了解下 index 指令,请求被内部重定向到第二个 location 了

回复 2022-09-16

直接访问域名 http://localhost,会匹配到第一个规则,但是 index 指令并不是找到文件之后就直接用了,而是会重新发起内部重定向,相当于从客户端发起 http://localhost/index.html ,所以会再一次匹配 location 配置。

知道原因之后就简单了,在配置中增加配置 location = /index.html 让 nginx 内部重定向到首页就好了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
server {
listen 80;
listen [::]:80;
server_name localhost;

#access_log /var/log/nginx/host.access.log main;

location = / {
root /usr/share/nginx/html;
index index.html;
}

location = /index.html {
root /usr/share/nginx/html;
}

location / {
proxy_pass http://192.168.0.10:8000;
}

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

}

重启 nginx 之后,就能实现直接访问域名展示首页,其余请求转发至后端服务了。

不得不提一点,Nginx location match tester 这个工具无法看出被转发的情况,比如上面的 index,它只会告诉你匹配到第一条规则了,但实际后面还有更多的动作,结果就是在这个工具里看到的结果与实际验证不一致,被这个点误导了很久。

参考

Nginx location match tester

一文理清 nginx 中的 location 配置(系列一)

nginx中的index配置