mateimarica / mateimarica.dev

Personal website with an Express.js backend.
https://mateimarica.dev
MIT License
0 stars 0 forks source link

[files] Large uploads timing out #18

Open mateimarica opened 1 year ago

mateimarica commented 1 year ago

When uploading large files (~2GB and above), the connection will often die after several minutes of uploading.

Progress bar stops moving:


Then, a minute or two later, this error is printed to the console. No extra info in the network tab.

Failed to load resource: net::ERR_CONNECTION_RESET

This is on Chrome, not tested on Firefox.


I suspect it has to do with the server timing-out the request. Needs more investigation.


The documentation for server.keepAliveTimeout:

Timeout in milliseconds. Default: 5000 (5 seconds). The number of milliseconds of inactivity a server needs to wait for additional incoming data, after it has finished writing the last response, before a socket will be destroyed. If the server receives new data before the keep-alive timeout has fired, it will reset the regular inactivity timeout, i.e., server.timeout.

It could be that if the client doesn't send a chunk of data for 5 seconds upload, the server kills the connection. This is more likely to happen during large (and long) uploads. In addition, there might be some network throttling (from the browser) occuring if the tab is not in focus during upload. This could play a role in the client not sending data frequently enough.

Read this article too, server.headersTimeout may need to be set too.

If possible, it would be preferable to increase this timeout only for the /upload endpoint.

mateimarica commented 1 year ago

Problem

It turns out the issue is with the new default node http.server options as of Node 18: (see docs)



So, the server will terminate any long-running request after 5 to 5:30 minutes, depending on when the connectionsCheckingInterval checker runs.


Desired Outcome


Solution

Now the problem is that requestTimeout seems to only be settable server-wide, rather than on a per-endpoint basis. Increasing the server-wide requestTimeout is a bad idea.

Googling this problem will give you people saying to add middleware to set timeouts directly to the req object. This doesn't work:

source

I tested the methods above on both the req and res objects, there's mixed answers on which one works. Either way, they do not affect the total timeout of a request.

Since I can only see requestTimeout being set server-wide, here are two bad solutions:

Both of these options are terrible. More research must be done.