Throttle nginx downloads based on model flag?

Hi, I’m trying to get Nginx to throttle downloads based on a flag set in the model of Django. When serving large files with the is_archived flag, I’d like to limit the download rate to 1 MB/s or lower so that downloads for archived files don’t disrupt downloading non-archived files. However, I can’t find a good way to get Django to tell Nginx that a given file has the flag set. What approach can I try here?

If the files to be served are located on the filesystem under a specific folder, so that they can be served by nginx using X-Accel (see X-Accel | NGINX). The response returned by django can then include the X-Accel-Redirect header to specify the file to be returned, and may also include X-Accel-Limit-Rate to limit the download rate.

If the files are served directly by the django app (returning a FileResponse), you may have the initial view serving files redirecting to another URL (whose corresponding view effectively returns the FileResponse) when archive flag is set, and configure that specific location in nginx configuration to limit bandwidth.

1 Like

Hmm, currently I’m serving files from the media/ directory with this nginx configuration:

Files that are “archived” are mixed with files that aren’t.

The files aren’t served directly by Django, so I guess that rules the latter approach out unless I rework it to go through Django. For the first one, would there be a way to send the X-Accel-Limit-Rate header with the configuration? That seems like the approach that I’m looking for – sending the rate limit header based on the flag in the model.

The general pattern for this is that the browser requests some url for a file - perhaps something like: /protected-media/file-name.png.

Your location directive for protected-media then routes that request to a Django view. That view checks whatever it needs to check to set headers (such as the X-Accel-Limit-Rate), then returns a redirect with the X-Accel-Redirect header set to indicate to nginx that this redirect is to be handled by nginx and not returned to the browser. The uri being used for the redirect would be the “real” url for the file.

In addition to the X-Accel docs referenced above, also see the docs for the internal directive, preventing users from accessing that real url directly.

So in this situation, Django isn’t actually sending the files, but it is processing the request to determine how the file should be handled. It’s still nginx serving the file.

2 Likes

@antoinehumbert @KenWhitesell thank you so much for the responses! I managed to implement it here: feat: throttle download speed for archived builds by ericswpark · Pull Request #289 · shipperstack/shipper · GitHub if anybody who finds this post is interested in an example.