Skip to content

Commit 66b3912

Browse files
committed
Add resproxy support
1 parent bde00c1 commit 66b3912

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

src/api.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,3 +457,20 @@ pub struct IpDetailsPlus {
457457
#[serde(flatten)]
458458
pub extra: HashMap<String, Value>,
459459
}
460+
461+
/// Residential proxy detection details.
462+
#[derive(Debug, Default, Deserialize, Serialize, Clone)]
463+
pub struct ResproxyDetails {
464+
/// The IP address.
465+
#[serde(default)]
466+
pub ip: String,
467+
468+
/// The last time this IP was seen as a residential proxy.
469+
pub last_seen: Option<String>,
470+
471+
/// The percentage of days seen as a residential proxy.
472+
pub percent_days_seen: Option<f64>,
473+
474+
/// The residential proxy service name.
475+
pub service: Option<String>,
476+
}

src/ipinfo.rs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use std::{collections::HashMap, num::NonZeroUsize, time::Duration};
1616

1717
use crate::{
1818
cache_key, is_bogon, Continent, CountryCurrency, CountryFlag, IpDetails,
19-
IpError, BATCH_MAX_SIZE, BATCH_REQ_TIMEOUT_DEFAULT, CONTINENTS, COUNTRIES,
20-
CURRENCIES, EU, FLAGS, VERSION,
19+
IpError, ResproxyDetails, BATCH_MAX_SIZE, BATCH_REQ_TIMEOUT_DEFAULT,
20+
CONTINENTS, COUNTRIES, CURRENCIES, EU, FLAGS, VERSION,
2121
};
2222

2323
use lru::LruCache;
@@ -428,6 +428,52 @@ impl IpInfo {
428428
Ok(report_url.unwrap().to_string())
429429
}
430430

431+
/// Looks up residential proxy details for a single IP address
432+
///
433+
/// # Example
434+
///
435+
/// ```no_run
436+
/// use ipinfo::IpInfo;
437+
///
438+
/// #[tokio::main]
439+
/// async fn main() {
440+
/// let ipinfo = IpInfo::new(Default::default()).expect("should construct");
441+
/// let res = ipinfo.lookup_resproxy("175.107.211.204").await.expect("should run");
442+
/// }
443+
/// ```
444+
pub async fn lookup_resproxy(
445+
&self,
446+
ip: &str,
447+
) -> Result<ResproxyDetails, IpError> {
448+
let response = self
449+
.client
450+
.get(format!("{BASE_URL}/resproxy/{ip}"))
451+
.headers(Self::construct_headers())
452+
.bearer_auth(self.token.as_deref().unwrap_or_default())
453+
.send()
454+
.await?;
455+
456+
// Check if we exhausted our request quota
457+
if let reqwest::StatusCode::TOO_MANY_REQUESTS = response.status() {
458+
return Err(err!(RateLimitExceededError));
459+
}
460+
461+
// Acquire response
462+
let raw_resp = response.error_for_status()?.text().await?;
463+
464+
// Parse the response
465+
let resp: serde_json::Value = serde_json::from_str(&raw_resp)?;
466+
467+
// Return if an error occurred
468+
if let Some(e) = resp["error"].as_str() {
469+
return Err(err!(IpRequestError, e));
470+
}
471+
472+
// Parse the results
473+
let details: ResproxyDetails = serde_json::from_str(&raw_resp)?;
474+
Ok(details)
475+
}
476+
431477
// Add country details and EU status to response
432478
fn populate_static_details(&self, details: &mut IpDetails) {
433479
if !&details.country.is_empty() {
@@ -617,4 +663,34 @@ mod tests {
617663
assert!(details.contains_key("4.2.2.4"));
618664
assert_eq!(details.len(), 2);
619665
}
666+
667+
#[tokio::test]
668+
async fn request_resproxy() {
669+
let ipinfo = get_ipinfo_client();
670+
671+
let details = ipinfo
672+
.lookup_resproxy("175.107.211.204")
673+
.await
674+
.expect("should lookup resproxy");
675+
676+
assert_eq!(details.ip, "175.107.211.204");
677+
assert!(details.last_seen.is_some());
678+
assert!(details.percent_days_seen.is_some());
679+
assert!(details.service.is_some());
680+
}
681+
682+
#[tokio::test]
683+
async fn request_resproxy_empty() {
684+
let ipinfo = get_ipinfo_client();
685+
686+
let details = ipinfo
687+
.lookup_resproxy("8.8.8.8")
688+
.await
689+
.expect("should lookup resproxy");
690+
691+
assert!(details.ip.is_empty());
692+
assert!(details.last_seen.is_none());
693+
assert!(details.percent_days_seen.is_none());
694+
assert!(details.service.is_none());
695+
}
620696
}

0 commit comments

Comments
 (0)