Skip to main content

melodium_repository/network/
remote.rs

1use std::path::PathBuf;
2
3use super::NetworkRepositoryConfiguration;
4use crate::global::Package as PackageDetails;
5use crate::technical::{Element, Package};
6use crate::{RepositoryError, RepositoryResult};
7use async_std::task::block_on;
8use http_client::{http_types::Url, HttpClient, Request};
9use once_cell::sync::OnceCell;
10
11pub fn get_tech_packages(
12    config: &NetworkRepositoryConfiguration,
13) -> RepositoryResult<Vec<Package>> {
14    let mut request =
15        Request::get(Url::parse(&format!("{}/packages.json", config.base_url)).unwrap());
16    request.insert_header("User-Agent", config.user_agent.clone());
17
18    block_on(async {
19        let mut response = http_client()
20            .send(request)
21            .await
22            .map_err(|err| RepositoryError::network_error(16, err.to_string()))?;
23
24        if response.status().is_success() {
25            let body = response
26                .body_string()
27                .await
28                .map_err(|err| RepositoryError::network_error(17, err.to_string()))?;
29
30            serde_json::from_str(&body).map_err(|err| RepositoryError::json_error(15, err))
31        } else {
32            Err(RepositoryError::network_error(
33                46,
34                response.status().canonical_reason().to_string(),
35            ))
36        }
37    })
38}
39
40pub fn get_detail_package(
41    config: &NetworkRepositoryConfiguration,
42    package: &Package,
43) -> RepositoryResult<PackageDetails> {
44    let mut request = Request::get(
45        Url::parse(&format!(
46            "{}/{}/package.json",
47            config.base_url,
48            package.get_path().to_string_lossy(),
49        ))
50        .unwrap(),
51    );
52    request.insert_header("User-Agent", config.user_agent.clone());
53
54    block_on(async {
55        let mut response = http_client()
56            .send(request)
57            .await
58            .map_err(|err| RepositoryError::network_error(41, err.to_string()))?;
59        if response.status().is_success() {
60            let body = response
61                .body_string()
62                .await
63                .map_err(|err| RepositoryError::network_error(42, err.to_string()))?;
64            serde_json::from_str(&body).map_err(|err| RepositoryError::json_error(43, err))
65        } else {
66            Err(RepositoryError::network_error(
67                47,
68                response.status().canonical_reason().to_string(),
69            ))
70        }
71    })
72}
73
74pub fn get_element_package(
75    config: &NetworkRepositoryConfiguration,
76    _element: Element,
77    url_path: PathBuf,
78    file_path: PathBuf,
79) -> RepositoryResult<()> {
80    let mut request = Request::get(
81        Url::parse(&format!(
82            "{}/{}",
83            config.base_url,
84            url_path.to_string_lossy(),
85        ))
86        .unwrap(),
87    );
88    request.insert_header("User-Agent", config.user_agent.clone());
89
90    block_on(async {
91        async_std::fs::create_dir_all(file_path.parent().unwrap_or(&PathBuf::default()))
92            .await
93            .map_err(|err| RepositoryError::fs_error(49, err))?;
94
95        let mut file = async_std::fs::File::create(file_path)
96            .await
97            .map_err(|err| RepositoryError::fs_error(34, err))?;
98
99        let mut response = http_client()
100            .send(request)
101            .await
102            .map_err(|err| RepositoryError::network_error(33, err.to_string()))?;
103
104        if response.status().is_success() {
105            async_std::io::copy(&mut response, &mut file)
106                .await
107                .map_err(|err| RepositoryError::fs_error(35, err))?;
108            Ok(())
109        } else {
110            Err(RepositoryError::network_error(
111                48,
112                response.status().canonical_reason().to_string(),
113            ))
114        }
115    })
116}
117
118fn http_client() -> &'static dyn HttpClient {
119    static CLIENT: OnceCell<http_client::h1::H1Client> = OnceCell::new();
120    CLIENT.get_or_init(|| http_client::h1::H1Client::new())
121}