很多 Nginx 问题,根源都不在代理、不在 HTTPS,而在 location 没想清楚。
先看一个例子:
server {
listen 80;
server_name example.com;
location = /healthz {
return 200 "ok\n";
}
location ^~ /assets/ {
root /srv/www/site;
}
location /api/ {
proxy_pass http://api_backend;
}
location ~* \.(png|jpg|jpeg|gif|svg|css|js)$ {
root /srv/www/site;
}
location / {
try_files $uri $uri/ /index.html;
}
}你要记住的匹配顺序,不是“看起来谁像谁”,而是固定规则:
1. 先查精确匹配:location = /xxx
2. 再找前缀匹配里“最长”的那一个
3. 如果这个最长前缀带 ^~,就停止,不再试正则
4. 否则按书写顺序检查正则 location
5. 正则没有命中,回到刚才记住的最长前缀可以压成一张小图:
请求 URI
|
+--> 精确匹配 = ?
| |
| +--> 命中,直接用
|
+--> 最长前缀是谁?
|
+--> 带 ^~ ? ----> 是 -> 直接用
|
+--> 否 -> 继续试正则
|
+--> 第一个命中的正则
|
+--> 没有 -> 回退到最长前缀这就是为什么 location 一乱,整个城市总闸口的分流就乱。
最常见的三种车道写法:
location = /healthz:只匹配一个点位,适合健康检查。location /api/:前缀车道,适合某个目录树。location ~ \.php$或location ~* \.(js|css)$:正则车道,适合模式匹配。