nullnet_libipinfo/
lib.rs

1#![doc = include_str!("../README.md")]
2
3pub use crate::api::api_fields::ApiFields;
4pub use crate::ip_info::IpInfo;
5pub use crate::ip_info_provider::IpInfoProvider;
6use crate::mmdb::mmdb_config::MmdbConfig;
7use crate::web_client::new_web_client;
8use nullnet_liberror::Error;
9use reqwest::Client;
10
11mod api;
12mod ip_info;
13mod ip_info_provider;
14mod mmdb;
15mod web_client;
16
17/// The main struct for handling IP information lookups.
18pub struct IpInfoHandler {
19    web_client: Client,
20    providers: Vec<IpInfoProvider>,
21    fallback: MmdbConfig,
22}
23
24impl IpInfoHandler {
25    /// Returns a new `IpInfoHandler` with the given providers.
26    ///
27    /// Even if no providers are given, the handler will still use a fallback provider
28    /// (free databases from [dp-ip.com](https://db-ip.com)).
29    #[allow(clippy::missing_errors_doc)]
30    pub fn new(providers: Vec<IpInfoProvider>) -> Result<Self, Error> {
31        let web_client = new_web_client()?;
32
33        let fallback = MmdbConfig::new(
34            "https://download.db-ip.com/free/dbip-city-lite-{%Y-%m}.mmdb.gz",
35            "https://download.db-ip.com/free/dbip-asn-lite-{%Y-%m}.mmdb.gz",
36            "",
37            31,
38        );
39
40        Ok(Self {
41            web_client,
42            providers,
43            fallback,
44        })
45    }
46
47    /// Looks up the IP information for the given IP address.
48    #[allow(clippy::missing_errors_doc)]
49    pub async fn lookup(&self, ip: &str) -> Result<IpInfo, Error> {
50        for provider in &self.providers {
51            let ip_info = provider.lookup_ip(&self.web_client, ip).await;
52            if ip_info.is_ok() {
53                return ip_info;
54            }
55        }
56        self.fallback.lookup_ip(ip)
57    }
58}