Skip to content

Latest commit

 

History

History
19 lines (11 loc) · 3.1 KB

README.md

File metadata and controls

19 lines (11 loc) · 3.1 KB

This example is part of a larger repository of examples, async-applied.

reqwest-tokio-compat

reqwest is an excellent crate for making HTTP requests in the vein of wget, curl, etc. tokio is the de facto Rust async runtime, especially for io-driven tasks. This example builds on the reqwest-tokio example. In that example we wondered why we could not call tokio::io::copy to copy the body of the reqwest::Response into outfile?

For reasons related to good API design a request::Response does not implement AsyncRead directly. It is, however, possible to convert it to a futures::io::Stream using bytes_stream(). A Stream is naught but an async iterator, analagous to how we called while let Some(chunk) = download.chunk().await? in the prior example. It is therefore not surprising that there is an stream extensions trait that allows us to go from a stream to a futures::io::AsyncRead. Note that, because AsyncRead uses futures::io::Error, we must map from request::Error in the process.

Having turned our reqwest::Response into an AsyncRead it should now be straightforward to invoke tokio::io::copy... but it is not. For reasons described here and here, futures::io::AsyncRead is not compatible with tokio::io::AsyncRead. Bummer. Fortunately there is a compatibility layer between tokio and futures!

The compatibility layer is found in a separate crate, tokio-util. To use it we pull in the appropriate extension trait:

use tokio_util::compat::FuturesAsyncReadCompatExt;

And then simply call compat() in the futures::io::AsyncRead to make it into a tokio::io::AsyncRead. Although it is annoying that futures and tokio have chosen not to use the same traits (at least for now), converting from one to the other really is not that hard.

Note: To use the compatibility layer you will need to use tokio-util version 0.3 or greater in your Cargo.toml.