1 - 需求
- 给某一个域名(假设为 a.com)重定向到 a.com/a ,需要将
/
的请求都重定向到/a
- /a 的路由没有在 nginx 中进行配置,而是在前端路由中进行配置的。
2 - 本地测试
本地没有前端的文件目录,我们配置一个 /a/
的路由来模拟
2.1 - 配置一
- 新增了一个 /a 的块,指定了文件路径
- 在 / 块中新增了 return 进行重定向
server {
listen 80;
listen [::]:80;
server_name localhost;
#access_log /var/log/nginx/host.access.log main;
location / {
return 301 /a;
}
location /a {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
问题一:
测试出现了 404,检查访问日志,请求的路径不对,于是有了配置二
分析:
nginx 中 alias 和 root 的逻辑是不一样的,alias 可以直接指定路径,而 root 会根据路由来自动匹配路径。
2.2 - 配置二
调整了如下配置
- root /usr/share/nginx/html;
+ alias /usr/share/nginx/html;
问题二:
调整后解决,但是发现进行了两次重定向:
分析:
根据重定向的变化可以发现,进行了路径补全,由/a 补全为了/a/,于是有了配置三。
2.3 - 配置三
调整为如下配置
location = / {
- return 301 /a;
+ return 301 /a/; # 直接指向带斜杠路径
}
测试,问题解决
3 - 生产配置
生产中,前端的项目是放置在 /usr/share/nginx/html
目录下面的
server {
listen 80;
listen 443 ssl;
server_name a.com;
ssl_certificate /etc/nginx/conf.d/cert/tinetcloud.com.pem;
ssl_certificate_key /etc/nginx/conf.d/cert/tinetcloud.com.key;
access_log /etc/nginx/conf.d/logs/access.log main;
error_log /etc/nginx/conf.d/logs/error.log debug;
location = / {
# 这里
return 301 /a;
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
try_files $uri $uri/ /index.html;
root /usr/share/nginx/html;
index index.html index.htm;
# 省略其它配置
}
3.1 - 思考
在这里我们配置的是 /a
结合我们本地测试的结果我们知道,配置 /a
和 /a/
的结果是不一样的,但是在上述配置中,配置 /a
和 /a/
的结果是一样的那么底层有什么区别呢?
观察配置,我们会发现有一个 try_files
的配置,我们需要先了解这个配置的含义,才能知道为什么会有这样的现象。
3.2 - try_files 机制
try_files $uri $uri/ /index.html;
$uri检测优先级:
/deepseek
→ 文件不存在(状态码404)/deepseek/
→ 目录不存在(状态码404)- 执行回退规则 →
/index.html;
3.3 - 最佳配置
省流:如果是目录,需要以 /
结尾
在有配置了 try_files 的情况下
try_files $uri $uri/ /index.html;
nginx 处理请求的链路图如下:
Nginx处理无斜杠请求并自动补全斜杠的逻辑流程:
总结
为什么要带斜杠?原因如下
阶段 | 带$uri/配置 | 不带$uri/配置 |
---|---|---|
文件检查阶段 | 文件检查→404 | 文件检查→404 |
目录检查阶段 | 目录检查→存在 | 跳过目录检查 |
SEO优化 | 自动规范URL格式 | 可能产生重复内容 |
安全防护 | 防止目录遍历攻击 | 暴露目录结构风险 |
缓存效率 | 独立缓存不同版本 | 混合缓存导致失效频繁 |
日志分析 | 明确区分文件和目录请求 | 无法识别请求类型差异 |