Skip Nginx reverse Proxy making duplicate requests on timeout for specific URL

Viewed 1858

Below is the code snippet from nginx configuration for the Rails application. The website is being accessed at localhost:5478 locally. Ports 5479-82 have ruby instances running to handle the traffic while serving requests. The application serves as backed api for multiple user facing applications which works for normal operations.

Issue is while uploading one of xls sheet from app, the import takes around 5 minutes and since operation times out, nginx makes the request on new port with same file. This results in duplicating entries in DB. Increasing the timeout will not help as size and content of file is unknown. I would like to control specific url's which should not go through reverse proxy flow. Should i go for new location blocks to solve this?

 upstream rails {
    ip_hash; 
    server 127.0.0.1:5479;
    server 127.0.0.1:5480;
    server 127.0.0.1:5481;
    server 127.0.0.1:5482;
  }

server {
listen          5478 default;
server_name     _;
root            "../protac/public";
add_header X-Frame-Options "SAMEORIGIN";

location ~ ^/assets/ {
  root "../protac/public";
  expires 1y;
  add_header Cache-Control public;

  add_header ETag "";
  break;
}

location ~* /  {


  # Setup redirection headers
  proxy_set_header   X-Real-IP         $remote_addr;
  proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
  proxy_set_header   Host              $http_host;

  proxy_buffer_size   128k;
  proxy_buffers   4 256k;
  proxy_busy_buffers_size   256k;

  # Pass the request thru
  proxy_pass         http://rails;
  add_header X-Frame-Options "SAMEORIGIN";
}
1 Answers

When you have several upstream servers configured, there's a proxy_next_upstream directive, that controls what happens if a request cannot be handled by one of the server, and by default, in case of a timeout or error getting a response, nginx will retry using another upstream.

See proxy_next_upstream documentation

If you don't want this behavior, and for your specific case (5 minutes of upload), you can use the proxy_next_upstream_timeout directive, that prevents it from trying a new upstream after a specified amount of time. Give it a reasonably low time to catch specifically those long timeouts.

Alternatively, you can define a specific location for such uploads, and set proxy_next_upstream off; for that location, to prevent this behavior only on that location.

Related