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?

1 Like

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 = "0.3.12", features = ["futures-io", "gzip"] }
futures = "0.3.21"
reqwest = { version = "0.11.10", features = ["stream"] }
tokio = { version = "0.17.0", 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(())
}
2 Likes

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

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.