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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright 2019 Ipregistry (https://ipregistry.co).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Official Rust client for the [Ipregistry](https://ipregistry.co) IP
//! geolocation and threat data API.
//!
//! Look up your own IP address or specified ones. Responses return multiple
//! data points including carrier, company, currency, location, time zone,
//! threat information, and more. The library can also parse raw User-Agent
//! strings.
//!
//! You'll need an Ipregistry API key, which you can get along with 100,000
//! free lookups by signing up for a free account at
//! <https://ipregistry.co>.
//!
//! # Quick start
//!
//! ```no_run
//! use std::net::IpAddr;
//! use ipregistry::Client;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let client = Client::new("YOUR_API_KEY");
//!
//! // Look up data for a given IPv4 or IPv6 address. On the server side,
//! // parse the client IP from the request headers.
//! let ip: IpAddr = "54.85.132.205".parse()?;
//! let info = client.lookup(ip).await?;
//! println!("{}", info.location.country.name);
//!
//! // Look up the IP address the request originates from.
//! let origin = client.lookup_origin().await?;
//! println!("{:?} {}", origin.info.ip, origin.info.location.country.name);
//!
//! Ok(())
//! }
//! ```
//!
//! Lookups are refined by chaining methods on the request before awaiting it:
//!
//! ```no_run
//! # async fn example(client: &ipregistry::Client, ip: std::net::IpAddr)
//! # -> Result<(), ipregistry::Error> {
//! let info = client
//! .lookup(ip)
//! .hostname(true) // resolve reverse-DNS hostname
//! .fields("location.country.name,security") // select only these fields
//! .await?;
//! # Ok(())
//! # }
//! ```
//!
//! # Batch lookups
//!
//! [`Client::lookup_batch`] resolves many IP addresses in a single request.
//! Each entry independently succeeds or fails (for example on a reserved
//! address), so entries are plain `Result` values:
//!
//! ```no_run
//! # async fn example(client: &ipregistry::Client) -> Result<(), ipregistry::Error> {
//! use std::net::IpAddr;
//!
//! let ips: Vec<IpAddr> = ["73.2.2.2", "8.8.8.8", "2001:67c:2e8:22::c100:68b"]
//! .iter()
//! .map(|s| s.parse().unwrap())
//! .collect();
//!
//! for entry in client.lookup_batch(ips).await? {
//! match entry {
//! Ok(info) => println!("{}", info.location.country.name),
//! Err(err) => eprintln!("entry failed: {err}"),
//! }
//! }
//! # Ok(())
//! # }
//! ```
//!
//! The Ipregistry API accepts up to [`MAX_BATCH_SIZE`] IP addresses per
//! request; larger inputs are transparently split into several requests
//! dispatched with bounded concurrency and reassembled in input order.
//!
//! # Caching
//!
//! Caching is disabled by default to ensure data freshness. Enable it by
//! passing an [`InMemoryCache`] — thread-safe, with LRU and TTL eviction — or
//! any [`Cache`] implementation of your own:
//!
//! ```no_run
//! use std::time::Duration;
//! use ipregistry::{Client, InMemoryCache};
//!
//! let cache = InMemoryCache::builder()
//! .max_size(8192)
//! .ttl(Duration::from_secs(600))
//! .build();
//!
//! let client = Client::builder("YOUR_API_KEY").cache(cache).build().unwrap();
//! ```
//!
//! # Errors
//!
//! All operations return [`Error`], which separates failures reported by the
//! API ([`Error::Api`], carrying a typed [`ErrorCode`]) from client-side
//! failures such as network errors ([`Error::Transport`]). See the [`Error`]
//! documentation for a matching example.
//!
//! # Runtime
//!
//! The client is asynchronous and runs on the [Tokio](https://tokio.rs)
//! runtime. A [`Client`] is cheap to clone and safe to share across tasks;
//! spawn concurrent lookups freely.
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
// The HTTP client type is part of the public API (see
// `ClientBuilder::http_client`); re-export it so downstream crates do not
// need to depend on a matching reqwest version themselves.
pub use reqwest;