1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::{
constants::{DEFAULT_REF, HOST, PROTOCOL, REGISTRY_PATH},
error::RegistryError,
};
use async_trait::async_trait;
use http::uri::Builder;
use serde::de::DeserializeOwned;
use std::path::PathBuf;
#[async_trait]
pub trait Fetchable
where
Self: DeserializeOwned,
{
fn path(resource: &str) -> PathBuf;
async fn fetch(chain_name: String, commit: Option<String>) -> Result<Self, RegistryError> {
let path = Self::path(chain_name.as_str());
let url = Builder::new()
.scheme(PROTOCOL)
.authority(HOST)
.path_and_query(
format!(
"{}/{}/{}",
REGISTRY_PATH,
commit.unwrap_or_else(|| DEFAULT_REF.to_string()),
path.clone()
.to_str()
.ok_or_else(|| RegistryError::path_error(path))?,
)
.as_str(),
)
.build()
.map_err(|e| RegistryError::url_parse_error(chain_name.to_string(), e))?;
let response = reqwest::get(url.to_string())
.await
.map_err(|e| RegistryError::request_error(url.to_string(), e))?;
if response.status().is_success() {
match response.text().await {
Ok(body) => match serde_json::from_str(&body) {
Ok(parsed) => Ok(parsed),
Err(e) => Err(RegistryError::json_parse_error(chain_name.to_string(), e)),
},
Err(e) => Err(RegistryError::request_error(url.to_string(), e)),
}
} else {
Err(RegistryError::status_error(
url.to_string(),
response.status().as_u16(),
))
}
}
}