ip_api4rs/
request_handler.rs1use crate::constant;
5use crate::error::IpApiError;
6use crate::model::ip_response::ErrorResponse;
7use governor::DefaultDirectRateLimiter;
8#[cfg(feature = "blocking")]
9use reqwest::blocking;
10use reqwest::RequestBuilder;
11use serde::de::DeserializeOwned;
12#[cfg(feature = "blocking")]
13use std::thread::sleep;
14#[cfg(feature = "blocking")]
15use std::time::Duration;
16
17pub async fn perform_get_request<T>(
26 request_builder: RequestBuilder,
27 limiter: &Option<DefaultDirectRateLimiter>,
28) -> Result<T, IpApiError>
29where
30 T: DeserializeOwned,
31{
32 wait_for_rate_limiter(limiter).await;
33 let response = request_builder.send().await?;
34 let json = response.text().await?;
35 process_result(json)
36}
37
38#[cfg(feature = "blocking")]
47pub fn perform_blocking_get_request<T>(
48 request_builder: blocking::RequestBuilder,
49 limiter: &Option<DefaultDirectRateLimiter>,
50) -> Result<T, IpApiError>
51where
52 T: DeserializeOwned,
53{
54 block_until_rate_limiter(limiter);
55 let response = request_builder.send()?;
56 let json = response.text()?;
57 process_result::<T>(json)
58}
59
60fn process_result<T>(json: String) -> Result<T, IpApiError>
69where
70 T: DeserializeOwned,
71{
72 if let Some(error) = validate_result(json.clone()) {
73 return Err(error);
74 }
75 parse_result::<T>(&json)
76}
77
78fn validate_result(json: String) -> Option<IpApiError> {
86 if json.contains("\"status\":\"fail\"") {
87 return match serde_json::from_str::<ErrorResponse>(&json) {
88 Ok(error_response) => match error_response.message.as_str() {
89 constant::ERROR_RESERVED_RANGE => Some(IpApiError::ReservedRange(error_response)),
90 constant::ERROR_INVALID_QUERY => Some(IpApiError::InvalidQuery(error_response)),
91 _ => Some(IpApiError::Unknown(json.clone())),
92 },
93 Err(err) => Some(IpApiError::JsonParseError(err)),
94 };
95 }
96 None
97}
98
99fn parse_result<T>(json: &str) -> Result<T, IpApiError>
107where
108 T: DeserializeOwned,
109{
110 match serde_json::from_str::<T>(json) {
111 Ok(response) => Ok(response),
112 Err(err) => Err(IpApiError::JsonParseError(err)),
113 }
114}
115
116async fn wait_for_rate_limiter(limiter: &Option<DefaultDirectRateLimiter>) {
118 if let Some(limiter) = limiter {
119 limiter.until_ready().await
120 }
121}
122
123#[cfg(feature = "blocking")]
125fn block_until_rate_limiter(limiter: &Option<DefaultDirectRateLimiter>) {
126 if let Some(limiter) = limiter {
127 while limiter.check().is_err() {
128 sleep(Duration::new(1, 0));
129 }
130 }
131}