blob: 5a686108293f7563a0db164511e8f047bf9d58ed [file] [log] [blame] [edit]
use std::collections::HashMap;
use std::time::Duration;
use anyhow::Result;
use curl::easy::{Easy2, Handler, WriteError};
use curl::multi::{Easy2Handle, Multi};
const URLS: &[&str] = &[
"https://www.microsoft.com",
"https://www.google.com",
"https://www.amazon.com",
"https://www.apple.com",
];
struct Collector(Vec<u8>);
impl Handler for Collector {
fn write(&mut self, data: &[u8]) -> Result<usize, WriteError> {
self.0.extend_from_slice(data);
Ok(data.len())
}
}
fn download(multi: &mut Multi, token: usize, url: &str) -> Result<Easy2Handle<Collector>> {
let version = curl::Version::get();
let mut request = Easy2::new(Collector(Vec::new()));
request.url(&url)?;
request.useragent(&format!("curl/{}", version.version()))?;
let mut handle = multi.add2(request)?;
handle.set_token(token)?;
Ok(handle)
}
fn main() -> Result<()> {
let mut multi = Multi::new();
let mut handles = URLS
.iter()
.enumerate()
.map(|(token, url)| Ok((token, download(&mut multi, token, url)?)))
.collect::<Result<HashMap<_, _>>>()?;
let mut still_alive = true;
while still_alive {
// We still need to process the last messages when
// `Multi::perform` returns "0".
if multi.perform()? == 0 {
still_alive = false;
}
multi.messages(|message| {
let token = message.token().expect("failed to get the token");
let handle = handles
.get_mut(&token)
.expect("the download value should exist in the HashMap");
match message
.result_for2(&handle)
.expect("token mismatch with the `EasyHandle`")
{
Ok(()) => {
let http_status = handle
.response_code()
.expect("HTTP request finished without status code");
println!(
"R: Transfer succeeded (Status: {}) {} (Download length: {})",
http_status,
URLS[token],
handle.get_ref().0.len()
);
}
Err(error) => {
println!("E: {} - <{}>", error, URLS[token]);
}
}
});
if still_alive {
// The sleeping time could be reduced to allow other processing.
// For instance, a thread could check a condition signalling the
// thread shutdown.
multi.wait(&mut [], Duration::from_secs(60))?;
}
}
Ok(())
}