从Nginx中的多个代理请求中捕获404

时间:2017-06-14 06:24:21

标签: redirect nginx error-handling proxy reverse-proxy

我在Debian Jessie上使用Nginx 1.10.3运行自我部署的应用程序,并进行以下设置。

Loadbalancer config:

upstream www {
    server [fda4::0:21]:8080 weight=80;
    server [fda4::0:22]:8080 weight=100;
    keepalive 100;
}
server {
    listen 80;
    server_name example.com;
    location / {
        rewrite ^/(.+)/+$ /$1 permanent;
        include /etc/nginx/proxy_params;
        proxy_set_header X-Forwarded-Host $host;
        proxy_pass http://www;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    }
}

后端配置:

server {
    listen [::]:8080 default_server backlog=1024;
    root /var/www/$host/web;
    index index.php;

    try_files $uri /index.php?$query_string;
    location ~ ^/index\.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        fastcgi_read_timeout 60s;
    }
}

我们有一个基于此设置的项目new-app,其中应该提供来自旧CMS(称为old-app)的内容,直到迁移完成。我的考虑是:

  • new-app中请求的网址不存在时,我们想查看old-app是否包含内容,因此new-app会抛出404
  • Nginx将此404和代理请求捕获到old-app
  • 如果old-app中有内容,则应与2xx / 3xx响应代码一起提供
  • 如果old-app中也没有内容,则会抛出额外的404
  • 这个404应该再次被Nginx捕获,并且应该在new-app内提供一个静态错误页面

这可以用Nginx完成吗?我想用

proxy_intercept_errors on;
error_page 404 = @404;
location @404 {
    proxy_pass http://old-app.domain;
}

可以做到这一点,但是当old-app也抛出404时,这不会启动无限循环的catch-and-proxy吗?干净的解决方案在old-app后端捕获404用于提供静态错误页面是什么样的?

1 个答案:

答案 0 :(得分:2)

如果您总是希望首先服务器new-app,除非出现错误,您可以使用两个位置块执行此操作:

upstream new-app {
    server [fda4::0:21]:8080 weight=80;
    server [fda4::0:22]:8080 weight=100;
    keepalive 100;
}

upstream old-app {
    server [fda4::0:21]:8081 weight=80;
    server [fda4::0:22]:8081 weight=100;
    keepalive 100;
}

server {
    listen 80;
    server_name example.com;
    recursive_error_pages on;

    location @old-app {
        rewrite ^/(.+)/+$ /$1 permanent;
        include /etc/nginx/proxy_params;
        proxy_set_header X-Forwarded-Host $host;
        proxy_pass http://old-app;
    }

    location / {
        rewrite ^/(.+)/+$ /$1 permanent;
        include /etc/nginx/proxy_params;
        proxy_set_header X-Forwarded-Host $host;
        proxy_pass http://new-app;
        proxy_intercept_errors on;
        error_page 404 = @old-app;
    }
}