isIPsafe
Rust logo

Rust

Check and report with reqwest and serde.

With reqwest and serde, checking and reporting take a few lines. Add to Cargo.toml:

[dependencies]
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Check and report

use serde::Deserialize;
use std::time::Duration;

const BASE: &str = "https://isipsafe.com/api/v1";

#[derive(Deserialize)]
struct CheckResponse {
    data: CheckData,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct CheckData {
    abuse_confidence_score: u8,
    total_reports: u32,
}

pub async fn score(client: &reqwest::Client, key: &str, ip: &str) -> reqwest::Result<u8> {
    let res: CheckResponse = client
        .get(format!("{BASE}/check"))
        .query(&[("ip", ip)])
        .bearer_auth(key)
        .timeout(Duration::from_secs(3))
        .send()
        .await?
        .error_for_status()?
        .json()
        .await?;
    Ok(res.data.abuse_confidence_score)
}

pub async fn report(client: &reqwest::Client, key: &str, ip: &str, categories: &str, comment: &str) -> reqwest::Result<()> {
    let res = client
        .post(format!("{BASE}/report"))
        .bearer_auth(key)
        .form(&[("ip", ip), ("categories", categories), ("comment", comment)])
        .timeout(Duration::from_secs(5))
        .send()
        .await?;
    // 429 means this address was already reported by you in the last 15 minutes.
    if res.status() != reqwest::StatusCode::TOO_MANY_REQUESTS {
        res.error_for_status()?;
    }
    Ok(())
}

#[tokio::main]
async fn main() -> reqwest::Result<()> {
    let client = reqwest::Client::new();
    let key = std::env::var("ISIPSAFE_KEY").unwrap_or_default();
    println!("score: {}", score(&client, &key, "203.0.113.7").await?);
    report(&client, &key, "203.0.113.50", "ssh,brute-force", "sshd: 300 failed passwords").await
}

In an axum or actix-web service, keep one Client for the whole process, cache scores (for example with moka) and treat lookup errors as a score of 0, so a slow network never blocks your users.

Need a hand?

If something here does not work with your version of Rust, or you have improved it, tell us. We update these pages with what people send.

Rust and its logo are trademarks of their respective owners. isipsafe is not affiliated with or endorsed by them.