ipwhois-rust 1.2.0

Official Rust client for the ipwhois.io IP Geolocation API. Simple, supports single and bulk IP lookups.
Documentation
//! Run with: `cargo run --example basic`

use ipwhois::{IpWhois, Options};

#[tokio::main]
async fn main() {
    /* -------------------------------------------------------------------
     * 1) Free plan — no API key, ~1 request/second per client IP.
     * ----------------------------------------------------------------- */
    let ipwhois = IpWhois::new();

    // All errors — invalid IP, network failure, bad options, … — come back
    // as `Err(Error)`. The library does not intentionally panic.
    match ipwhois.lookup("8.8.8.8").await {
        Ok(info) => {
            println!(
                "{}  {}  ({}, {})",
                info.ip.as_deref().unwrap_or(""),
                info.flag
                    .as_ref()
                    .and_then(|f| f.emoji.as_deref())
                    .unwrap_or(""),
                info.country.as_deref().unwrap_or("unknown"),
                info.city.as_deref().unwrap_or("unknown"),
            );
        }
        Err(e) => {
            eprintln!("Lookup failed: {}", e.message());
            std::process::exit(1);
        }
    }

    /* -------------------------------------------------------------------
     * 2) Look up the caller's own IP — use `lookup_self`.
     * ----------------------------------------------------------------- */
    if let Ok(me) = ipwhois.lookup_self().await {
        println!(
            "My IP: {}{}",
            me.ip.as_deref().unwrap_or(""),
            me.country.as_deref().unwrap_or(""),
        );
    }

    /* -------------------------------------------------------------------
     * 3) Paid plan — supply the API key.
     * ----------------------------------------------------------------- */
    let paid = IpWhois::with_key("YOUR_API_KEY");

    let opts = Options::new()
        .with_lang("en") // localised country / city / …
        .with_fields(["success", "country", "city", "connection.isp", "flag.emoji"])
        .with_security(true) // include proxy / vpn / tor flags
        .with_rate(true); // include rate-limit info

    match paid.lookup_with("1.1.1.1", &opts).await {
        Ok(info) => println!("{:#?}", info),
        Err(e) => eprintln!("error ({}): {}", e.error_type(), e.message()),
    }
}