Nginx – Proxy Pass Only if File Exists on Proxy Server

nginxproxypassrewrite

I'm familiar with the practice of serving a static file if it exists, and passing everything else off to index.php.

Can this be used in conjunction with proxy passing and whether the static file exists on the proxy server?

For example, let's say I have these two servers:

Server 1:

  • index.php
  • stylesheet.css

Server 2 (proxy):

  • about/index.html
  • contact.html

example.com is set to resolve to Server 1. When the request comes in, the nginx config looks at the incoming URL, and sees if it maps to a file on Server 2. If so, it proxies the request to the file on Server 2. If the file does not exist, it just keeps it on Server 1. On Server 1, though, it still prefers files that exist, and maps other routes to index.php.

If that's confusing, here are some examples

  • example.com/about –> maps to Server 2, about/index.html
  • example.com/contact.html –> maps to Server 2, contact.html
  • example.com/careers –> maps to Server 1, index.php
  • example.com/stylesheet.css –> maps to Server 1, stylesheet.css

In cases where the same file exists on both servers, it should map to Server 2.

Best Answer

Disclaimer: this is not an efficient way to operate a reverse proxy.

You reverse proxy every request to server 2, and if that server cannot satisfy the request, it responds with a 404 status.

Server 1 can handle a 404 status by setting proxy_intercept_errors and error_page.

For example:

location / {
    proxy_pass ...;
    proxy_intercept_errors on;
    error_page 404 = @fallback;
}
location @fallback {
    try_files $uri /index.php;
}
location ~ \.php$ {
    try_files $uri =404;
    include         fastcgi_params;
    fastcgi_param   SCRIPT_FILENAME $request_filename;
    fastcgi_pass    ...;
}

The only exception is URIs ending with .php will not be sent to server2 first. See this document for details.