pkg/net_backend/
reqwest_backend.rs1use 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}