How to stream async `reqwest::Response` to `GzDecoder`?

I am trying to extract the downloaded tarbell from reqwest with flate2::bufread::GzDecoder. I have seen a very similar question, but that doesn't work as only reqwest::blocking::Response has implemented the Read trait.

And for reqwest::Response, it hasn't implemented BufRead or Read. How can I pass the response body as byte into the GzDecoder?

It looks like flate2 removed async support in PR #292, recommending the now-popular async-compression crate as an alternative. With it, you have to do a bit of work to get a GzipDecoder:

[dependencies]
async-compression = { version = "*", features = ["futures-io", "gzip"] }
futures = "*"
reqwest = { version = "*", features = ["stream"] }
tokio = { version = "*", features = ["full"] }
use std::error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn error::Error>> {
    use async_compression::futures::bufread::GzipDecoder;
    use futures::{
        io::{self, BufReader, ErrorKind},
        prelude::*,
    };
    let response = reqwest::get("http://localhost:8000/test.txt.gz").await?;
    let reader = response
        .bytes_stream()
        .map_err(|e| io::Error::new(ErrorKind::Other, e))
        .into_async_read();
    let mut decoder = GzipDecoder::new(BufReader::new(reader));
    let mut data = String::new();
    decoder.read_to_string(&mut data).await?;
    println!("{data:?}");
    Ok(())
}
1 Like

I don't mind switch crate and this is perfect. Thanks!