1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Project: factbook
// File: src/geoip/mod.rs
// Purpose: GeoIP databases: configuration and provisioning
// Language: Rust
//
// License: Apache-2.0
// Copyright: (c) 2026 HYPERI PTY LIMITED
//! GeoIP databases: which ones a service wants, getting them onto disk, and
//! looking addresses up in them.
//!
//! [`GeoIpConfig`] describes the databases and [`ensure_databases`] provisions
//! them. An app checks its configuration with [`validate`] when it loads it,
//! because provisioning itself never fails loudly. [`GeoIp`] reads the
//! provisioned files behind a cache and answers with a [`GeoIpRecord`].
//!
//! # Non-fatal by contract
//!
//! [`ensure_databases`] returns `Ok` with `None` entries when a download fails.
//! A GeoIP database going missing degrades enrichment; it must not stop a
//! service from starting. Failures are logged at `warn` and a stale local file
//! is preferred over no file at all.
//!
//! # Credentials
//!
//! MaxMind and IPinfo credentials are [`Secret`](crate::Secret) and never reach
//! a log line. The IPinfo token is attached as a query parameter by the request
//! builder rather than being formatted into the URL string, and a transport
//! error is stripped of its URL before it is reported, so neither the logged URL
//! nor the error text can carry it.
//!
//! # Example
//!
// The example provisions, so it only compiles where the download half does.
// Marked `ignore` otherwise: a lookup-only build has no `GeoIpConfig` to name.
//! use factbook::geoip::{GeoIpConfig, ensure_databases};
//!
//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
//! let databases = ensure_databases(&GeoIpConfig::default()).await?;
//! if let Some(city) = databases.city {
//! println!("city database is {:?} in {:?}", city.format, city.files);
//! }
//! # Ok(())
//! # }
//! ```
// Private, with every public item re-exported below: the module layout is not
// part of the API, so it can be rearranged without a major version. The table
// half is arranged the same way.
pub
pub
// One MaxMind DB encoder, shared by the two suites that build their own file.
pub use ;
pub use ;
pub use ;
pub use is_private;
pub use ;
/// Default ceiling, in bytes, under which a database is read into memory rather
/// than mapped.
///
/// 128 MiB clears every database measured -- sapics `origin-asn` at 10 MB,
/// IPinfo Lite at 23 MB, GeoLite2-City at 70 MB and DB-IP Lite at 100-120 MB
/// expanded -- leaving the 120 MB paid city builds as the first to cross it as
/// they grow.
pub const DEFAULT_RESIDENT_MAX_BYTES: u64 = 128 * 1024 * 1024;