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
17pub struct IpInfoHandler {
19 web_client: Client,
20 providers: Vec<IpInfoProvider>,
21 fallback: MmdbConfig,
22}
23
24impl IpInfoHandler {
25 #[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 #[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}