melodium_repository/network/
remote.rs1use 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}