0

Project Description

I'm working on a NodeJS/Express application that, on loading the home page, uses Fetch to call a route that makes an API request. The data retrieved from the API request is returned to the client into a dropdown.

Problem

The API request often takes longer than 2 minutes to return a response, which causes Fetch to timeout with a 504 Gateway Timeout. It's my understanding the default timeout for Express is 2 minutes, so I've tried numerous ways to increase this timeout but have had no luck. It may be worth noting that I only get these timeout errors when testing the deployed code. When I test by running the code locally, I get no errors, and the 2 minute timeout does not appear to exist. Enforcing a timeout using some of the attempts below would cause a timeout when running locally.

Fix Attempts

  1. Using the Express connect-timeout middleware as described here. I tested as a top-level middleware, and within the route itself.

  2. Setting the server timeout after the app.listen() function:

     var server = app.listen(port, () => console.log(`Listening on port ${port}...`));
     server.setTimeout(3 * 60 * 1000);
    
  3. Setting the keepAliveTimeout and headersTimeout after the app.listen() function:

     var server = app.listen(port, () => console.log(`Listening on port ${port}...`));
     server.keepAliveTimeout = 30000; 
     server.headersTimeout = 31000;
    
  4. Setting the request timeout within the route called from Fetch:

     router.post('/example', function (req, res) {
         req.setTimeout(3 * 60 * 1000);
         // Call function that makes API request
         return res.send(api_response_data);
     });
    

Stack Overflow Threads Used

How to set the HTTP Keep-Alive timeout in a nodejs server

How to modify the nodejs request default timeout time?

Express.js connect timeout vs server timeout

Express.js Response Timeout

Express.js HTTP request timeout

Most of the attempts listed above are reflected in these threads; however, I tried almost all suggestions found these threads as well.

GriffsAccount
  • 95
  • 1
  • 12
  • `504 Gateway Timeout` sounds like it's coming from some part of the hosting infrastructure as it tries to clean up "stuck" http requests, and may not be coming from your server directly. I'd suggest researching http timeout settings in your hosting plan. – jfriend00 Dec 15 '21 at 16:43
  • I was thinking that might be the case. Will look into it, thanks! – GriffsAccount Dec 15 '21 at 17:07
  • FYI, it is not uncommon that long running http requests can be problematic. If there is really no way to make it not so long running on the server, then there are ways to design around that such as using a webSocket connection instead. The client sends a request over the webSocket connection and then the server sends a response back some long time later, whenever the response is ready. Since a webSocket connection is already designed to be long running and all infrastructure (that supports webSockets) should be aware of that, you are likely to have fewer problems. – jfriend00 Dec 15 '21 at 17:28
  • There really isn't another way for me to make the requests shorter unfortunately... So I would still use Node and Express, but implement WebSockets? I'm unfamiliar, so any resources or suggestions would be very helpful! – GriffsAccount Dec 15 '21 at 18:36
  • A webSocket connection is just a long running connection between client and server which either side can send data over at any time. The useful part of it in this circumstance is that the server can send data over the webSocket (when it finally gets its result) without the client having to hang onto an http connection waiting for the final response - thus avoiding timeout issues. This is often referred to as "server push" where the server can just proactively send data to the client without the client having to specifically request it. – jfriend00 Dec 15 '21 at 19:23
  • There are thousands of articles on the web about webSockets and about socket.io connections which are a higher level layer (easier to use) built on top of webSockets so I won't try to repeat all that here. You can read many of those articles to get a foundation on how they work, what you could use them for. – jfriend00 Dec 15 '21 at 19:24
  • Sounds good. Appreciate the help with this. Will give webSockets a try. – GriffsAccount Dec 15 '21 at 19:33
  • Web sockets are a good solution, one that I prefer, but depending on your needs you might find long polling simpler to implement. The client would make the initial request and an immediate response from the server would be sent, usually with some uri that can be used to check the status of the api request, and then keep making requests from the client every 1s of so to see if the api request is complete. – James Dec 15 '21 at 20:14

1 Answers1

0

I used @jfiend00's suggestion and redesigned my application to use a WebSocket connection. I no longer run into timeout issues as long as I have occasional ping/pong messages sent between the server and client to keep the connection alive.

GriffsAccount
  • 95
  • 1
  • 12