The cross-platform version manager toolset crates.io/crates/hyper-jump
at partner-chains-support 96 lines 2.8 kB view raw
1use std::borrow::Cow; 2 3use anyhow::anyhow; 4use anyhow::Result; 5use reqwest::Client; 6use serde::de::DeserializeOwned; 7use serde::Deserialize; 8use serde::Serialize; 9 10/// Represents an error response from the GitHub API. 11/// 12/// This struct contains information about an error response from the GitHub 13/// API, including the error message and the URL of the documentation related to 14/// the error. 15/// 16/// # Fields 17/// 18/// * `message: String` - The error message from the GitHub API. 19/// * `documentation_url: String` - The URL of the documentation related to the 20/// error. 21/// 22/// # Example 23/// 24/// ```rust 25/// let error_response = ErrorResponse { 26/// message: "Not Found".to_string(), 27/// documentation_url: "https://docs.github.com/rest".to_string(), 28/// }; 29/// println!("The error message is {}", error_response.message); 30/// println!( 31/// "The documentation URL is {}", 32/// error_response.documentation_url 33/// ); 34/// ``` 35#[derive(Debug, Deserialize, Serialize)] 36pub struct ErrorResponse { 37 pub message: String, 38 pub documentation_url: String, 39} 40 41pub async fn api(client: Option<&Client>, url: String) -> Result<String> { 42 let response = client 43 .expect("Client not found") 44 .get(url) 45 .header(reqwest::header::USER_AGENT, "hyper-jump") 46 .header(reqwest::header::ACCEPT, "application/vnd.github.v3+json") 47 .send() 48 .await? 49 .error_for_status()? 50 .text() 51 .await?; 52 53 Ok(response) 54} 55 56/// Deserializes a JSON response from the GitHub API. 57/// 58/// # Parameters 59/// 60/// * `response: String` - The JSON response from the GitHub API as a string. 61/// 62/// # Returns 63/// 64/// * `Result<T>` - The deserialized response as the specified type `T`, or an 65/// error if the response could not be deserialized or contains an error 66/// message. 67/// 68/// # Errors 69/// 70/// This function will return an error if the response contains a "message" 71/// field (indicating an error from the GitHub API), or if the response could 72/// not be deserialized into the specified type `T`. 73/// 74/// # Example 75/// 76/// ```rust 77/// let response = "{\"data\": \"some data\"}"; 78/// let result: Result<MyType> = deserialize_response(response); 79/// match result { 80/// Ok(data) => println!("Received data: {:?}", data), 81/// Err(e) => println!("An error occurred: {:?}", e), 82/// } 83/// ``` 84pub fn deserialize_response<T: DeserializeOwned>(response: String) -> Result<T> { 85 let value: serde_json::Value = serde_json::from_str(&response)?; 86 if value.get("message").is_some() { 87 let result: ErrorResponse = serde_json::from_value(value)?; 88 if result.documentation_url.contains("rate-limiting") { 89 return Err(anyhow!("Rate limited by GitHub API")); 90 } 91 92 return Err(anyhow!(result.message)); 93 } 94 95 Ok(serde_json::from_value(value)?) 96}