ip_api4rs/
lib.rs

1//! # IP-API4rs
2//!
3//! A simple Rust crate for the [ip-api.com](https://ip-api.com) API.
4
5use governor::{DefaultDirectRateLimiter, Quota, RateLimiter};
6use nonzero_ext::nonzero;
7use reqwest::Client;
8use serde::de::DeserializeOwned;
9
10use model::ip_response::{IpDefaultResponse, IpFullResponse};
11
12use crate::client::{AsyncIpApi, IpApi};
13use crate::error::IpApiError;
14
15#[cfg(feature = "blocking")]
16pub mod blocking;
17pub mod client;
18pub mod constant;
19pub mod error;
20pub mod model;
21pub mod request_handler;
22pub mod util;
23
24/// The main client for the ip-api.com API.
25pub struct IpApiClient {
26    /// The client to use for the requests.
27    pub client: Client,
28    /// The rate limiter to use for the requests.
29    pub limiter: Option<DefaultDirectRateLimiter>,
30    /// The API key to use for the requests.
31    pub api_key: Option<String>,
32}
33
34impl Default for IpApiClient {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40impl IpApiClient {
41    /// Creates a new BlockingIpApiClient with no API key.
42    pub fn new() -> Self {
43        Self {
44            client: Client::new(),
45            limiter: Some(RateLimiter::direct(Quota::per_minute(nonzero!(45u32)))),
46            api_key: None,
47        }
48    }
49
50    /// Creates a new IpApiClient with an API key.
51    pub fn new_with_api_key(api_key: String) -> Self {
52        Self {
53            client: Client::new(),
54            limiter: None,
55            api_key: Some(api_key),
56        }
57    }
58}
59
60impl IpApi for IpApiClient {
61    fn get_api_key(&self) -> &Option<String> {
62        &self.api_key
63    }
64
65    fn get_rate_limiter(&self) -> &Option<DefaultDirectRateLimiter> {
66        &self.limiter
67    }
68}
69
70impl AsyncIpApi for IpApiClient {
71    async fn query_api_default(&self, ip: &str) -> Result<IpDefaultResponse, IpApiError> {
72        let request = util::requests::get_default_async_get_request(&ip.to_string(), self);
73        request_handler::perform_get_request::<IpDefaultResponse>(request, &self.limiter).await
74    }
75
76    async fn query_api_fully(&self, ip: &str) -> Result<IpFullResponse, IpApiError> {
77        let request = util::requests::get_async_request::<IpFullResponse>(&ip.to_string(), self);
78        request_handler::perform_get_request::<IpFullResponse>(request, &self.limiter).await
79    }
80
81    async fn query_api<T>(&self, ip: &str) -> Result<T, IpApiError>
82    where
83        T: DeserializeOwned,
84    {
85        let request = util::requests::get_async_request::<T>(&ip.to_string(), self);
86        request_handler::perform_get_request::<T>(request, &self.limiter).await
87    }
88
89    fn get_http_client(&self) -> &Client {
90        &self.client
91    }
92}