nginx:当 proxy_pass 失败时回退到 try_files 需要不寻常的配置

st-*_*t-h 7 nginx proxypass single-page-application

我正在使用 Nginx 为单页应用程序提供服务。基本上我们只需要index.html在没有找到匹配文件时提供页面。该位置看起来像这样并且一直运行良好:

location / {
   try_files $uri $uri/ /index.html
}
Run Code Online (Sandbox Code Playgroud)

现在我想查询一个上游服务器,只有当失败时,才使用try_files上面的指令

如果try_files刚刚移动到后备位置,如

location @fallback {
  try_files $uri $uri/ /index.html;
}

location / {
  proxy_pass http://127.0.0.1:8080;
  proxy_intercept_errors on;
  error_page 400 403 502 503 504 @fallback;
}
Run Code Online (Sandbox Code Playgroud)

然后 - 当上游服务器不可用时 - 客户端会看到 Nginx 502 错误页面,而不是文件系统提供的文件。

我终于找到了一个解决方案,该解决方案通过在 /index.html 回退前使用双斜线起作用。这是整个配置文件,可以与官方 nginx docker 镜像一起用于测试

events {
} 

http {

  error_log /var/log/nginx/error.log;
  access_log /var/log/nginx/access.log;

  server {

    listen 80;

    root /usr/share/nginx/html/;

    location / { 
      proxy_pass http://127.0.0.1:9990;
      proxy_intercept_errors on; 
      error_page 400 403 502 503 504 = @fallback;
    }

    location @fallback {
      try_files $uri?$args /index.html //index.html;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

可以使用类似的命令运行

docker run -v /path/to/www/folder:/usr/share/nginx/html:ro -v /path/to/config/nginx.conf:/etc/nginx/nginx.conf -d -p 8080:80 nginx
Run Code Online (Sandbox Code Playgroud)

如果在最后一个index.html回退之前没有双斜线,比如

location @fallback {
  try_files $uri?$args /index.html;
}
Run Code Online (Sandbox Code Playgroud)

然后 nginx 在文件系统上构造一个路径,例如<root>index.html,它缺少分隔符而不是正确的<root>/index.html,每当请求不是根 url 的 url 时。

最后一个问题:为什么这个设置需要在 try_files 指令中使用双斜杠?为什么不能只使用常规配置中的 try_files 部分并将其移动到拦截错误时使用的回退位置?

Fél*_*ier 3

我遇到了类似的情况,我使用此常见陷阱页面中的建议以相反的方式解决了这个问题。也就是说,首先提供静态文件,然后回退到代理:

location / {
    try_files $uri $uri/ @proxy;
}
location @proxy {
    proxy_pass http://127.0.0.1:9990;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,这将首先在根目录中查找静态文件是否存在,然后将请求代理到http://127.0.0.1:9000。这在功能上是等效的,除非您希望代理中的文件隐藏静态文件。