1use std::{io::Cursor, str::FromStr, time::Duration};
2
3use reqwest::{Method, Request, StatusCode, Url};
4use tracing::trace;
5
6use crate::constants::THIS_IS_A_BUG;
7
8type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
9
10pub async fn download_file(url: String, dest: String) -> Result<()> {
11 let response = reqwest::get(url).await?;
12 let mut file = std::fs::File::create(dest)?;
13 let mut content = Cursor::new(response.bytes().await?);
14 std::io::copy(&mut content, &mut file)?;
15 Ok(())
16}
17
18pub async fn wait_ws_ready(url: &str) -> Result<()> {
19 let mut parsed = Url::from_str(url)?;
20 parsed
21 .set_scheme("http")
22 .map_err(|_| anyhow::anyhow!("Can not set the scheme, {}", THIS_IS_A_BUG))?;
23
24 let http_client = reqwest::Client::new();
25 loop {
26 let req = Request::new(Method::OPTIONS, parsed.clone());
27 let res = http_client.execute(req).await;
28 match res {
29 Ok(res) => {
30 if res.status() == StatusCode::OK {
31 break;
33 }
34
35 trace!("http_client status: {}, continuing...", res.status());
36 },
37 Err(e) => {
38 if !skip_err_while_waiting(&e) {
39 return Err(e.into());
40 }
41
42 trace!("http_client err: {}, continuing... ", e.to_string());
43 },
44 }
45
46 tokio::time::sleep(Duration::from_secs(1)).await;
47 }
48
49 Ok(())
50}
51
52pub fn skip_err_while_waiting(e: &reqwest::Error) -> bool {
53 e.is_connect() || e.is_request()
60}