Stream an upload and read a download in chunks
For Rust developers moving bodies too big to hold in memory
You upload a file straight from disk without reading it into memory first, then read a download piece by piece as it arrives.
Before you start
You need Rust with Cargo. fibre_http comes from crates.io:
fibre_http = "0"Set up the project#
Start a new binary crate.
Put this in the [dependencies] section of Cargo.toml:
[]
= { = "0", = ["json"] }
= "1"The json feature is only there to read httpbin's answer to the upload.
The program#
The program writes a small file to upload, sends it to httpbin.org's /put and then downloads 100,000 bytes from /stream-bytes. Replace src/main.rs with this:
use File;
use Write;
use SyncClient;
use Value;
Run it:
The number of chunks changes from run to run, since it depends on how the bytes arrive over the network. The total is always 100000.
What each part does#
body_reader takes anything that implements std::io::Read and sends it as the request body while reading it. Passing the length lets the client send a Content-Length header, which some servers require. Pass None when you do not know the length and the body goes out in chunks instead.
A streamed body can only be read once. So a request with one is never retried. A 307 or 308 redirect comes back to you as the response instead of being followed.
into_body() hands you the response body without reading it. Each call to chunk() returns the next piece as it arrives and None at the end. A blocking body also implements std::io::Read, so std::io::copy works on it too.
If you drop a body before its end, the client closes that exchange so the connection is not left holding unread bytes.
Where to go next#
The async client has the same calls: body_stream sends a stream of byte chunks and chunk().await reads a body piece by piece. The usage guide has both: https://github.com/excsn/fibre/blob/main/http/README.USAGE.md
