Large file download fails on slow network using HTTP/2 and AWS ALB
Given the following architecture:
client <-> AWS ALB <-> uwsgi <-> Django
The client fails to download a 12MB file when using HTTP/2 (the default), but works using HTTP/1.1. The file is streamed through Django for authentication purposes (it's fetched from a third party service).
Here is an example of failure (I'm using a Socks proxy to limit bandwidth):
$ curl -x socks5://localhost:1080 https://example.com/file.pdf --output "file.pdf"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
79 12.6M 79 10.0M 0 0 61254 0 0:03:36 0:02:51 0:00:45 64422
curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
However the same command with the flag --http1.1
works fine.
This fails when I limit downloads to 512kbps - it works at 1024Kbps. I've not looked for the sweet spot, it's not important.
Notes:
- This also fails with a browser, it's not a
curl
issue - Using
curl
with-v
doesn't give any additional information. uwsgi
does not output any errors. As far as it's concerned it did it's job. This is the output:[pid: 44|app: 0|req: 2603/9176] [ip] () {34 vars in 639 bytes} [Wed Oct 16 09:29:29 2024] GET /file.pdf => generated 13243923 bytes in 2425 msecs (HTTP/1.1 200) 8 headers in 314 bytes (103471 switches on core 0)
- Similarly there are no issues listed in the ALB logs. It logs the request as a succesful request, but with a number of bytes lower than the expected amount.
I'd like to understanding why it's failing with HTTP/2 and a slow network. I suspect it's something to do with the ALB.
There are two things that could be done and people might suggest:
- Put Nginx between the ALB and uwsgi
- Don't stream the file through Django
Both of these are valid suggestions, however I'd like to understand what the problem is before deciding on a solution.