pkg/net_backend/
reqwest_backend.rs

1use std::{
2    cell::RefCell,
3    fs::File,
4    io::{Read, Write},
5    path::Path,
6    rc::Rc,
7    time::Duration,
8};
9
10use super::{Callback, DownloadBackend, DownloadError};
11
12#[derive(Clone)]
13pub struct ReqwestBackend {
14    client: reqwest::blocking::Client,
15}
16
17impl DownloadBackend for ReqwestBackend {
18    fn new() -> Result<Self, DownloadError> {
19        let client = reqwest::blocking::Client::builder()
20            .brotli(true)
21            .timeout(Duration::new(5, 0))
22            .build()?;
23        Ok(Self { client })
24    }
25
26    fn download(
27        &self,
28        remote_path: &str,
29        local_path: &Path,
30        callback: Rc<RefCell<dyn Callback>>,
31    ) -> Result<(), DownloadError> {
32        let mut callback = callback.borrow_mut();
33
34        let mut resp = self.client.get(remote_path).send()?.error_for_status()?;
35
36        let len: u64 = resp.content_length().unwrap_or(0);
37
38        let mut output = File::create(local_path)?;
39
40        callback.start_download(len, remote_path);
41
42        let mut data = [0; 8192];
43        loop {
44            let count = resp.read(&mut data)?;
45            output.write(&data[..count])?;
46            if count == 0 {
47                break;
48            }
49            callback.increment_downloaded(count);
50        }
51        output.flush()?;
52
53        callback.end_download();
54
55        Ok(())
56    }
57}