From 300b827915bd4bb9cc5fb59aa42b15ac8521c27a Mon Sep 17 00:00:00 2001 From: videogame hacker Date: Thu, 30 Dec 2021 18:10:50 +0000 Subject: [PATCH] Hook up the range data to the API --- Cargo.lock | 16 ++++++++++++++++ Cargo.toml | 2 ++ src/main.rs | 45 ++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f3d597e..a655b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,8 @@ name = "geoip-api" version = "0.1.0" dependencies = [ "itertools", + "serde", + "serde_json", "tokio", "warp", ] @@ -646,6 +648,20 @@ name = "serde" version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "serde_json" diff --git a/Cargo.toml b/Cargo.toml index ccc1d22..2d910b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,7 @@ authors = ["charlotte ✨ "] [dependencies] itertools = "0.10.3" +serde = { version = "1.0.132", features = ["derive"] } +serde_json = "1.0.73" tokio = { version = "1.15.0", features = ["full"] } warp = "0.3.2" diff --git a/src/main.rs b/src/main.rs index df0b923..f2a7f32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,18 @@ use itertools::Itertools; +use serde::Serialize; use std::{net::Ipv4Addr, sync::Arc}; -use warp::Filter; +use warp::{http::StatusCode, reply, Filter}; + +use serde_json::json; const IP2ASN_DATA: &str = include_str!("../data/ip2asn-v4.tsv"); -#[derive(Debug)] +#[derive(Serialize)] struct RangeRecord { + #[serde(skip)] ip_start: Ipv4Addr, + #[serde(skip)] ip_end: Ipv4Addr, asn: u64, country_code: &'static str, @@ -38,13 +43,43 @@ fn parse_ranges() -> Vec { ranges } +type RangeData = Arc>; +fn with_ranges( + ranges: RangeData, +) -> impl Filter + Clone { + warp::any().map(move || ranges.clone()) +} + +fn get_range_data(ip: String, ranges: RangeData) -> impl warp::Reply { + if let Ok(ipv4) = ip.parse::() { + for range in ranges.iter() { + if (range.ip_start..=range.ip_end).contains(&ipv4) { + return reply::with_status(reply::json(&range), StatusCode::OK); + } + } + + reply::with_status( + reply::json(&json!({ "error": "range not found" })), + StatusCode::NOT_FOUND, + ) + } else { + reply::with_status( + reply::json(&json!({ "error": "invalid ipv4 address" })), + StatusCode::BAD_REQUEST, + ) + } +} + #[tokio::main] async fn main() { eprintln!("[i] Parsing IP ASN data..."); - let _ranges = Arc::new(parse_ranges()); + let ranges: RangeData = Arc::new(parse_ranges()); eprintln!("[i] Done!"); - let hello = warp::any().map(|| "Hello!".to_string()); + let get_ip_data = warp::path!(String) + .and(with_ranges(ranges.clone())) + .map(get_range_data); + println!("\nListening on http://127.0.0.1:8000 ..."); - warp::serve(hello).bind(([127, 0, 0, 1], 8000)).await; + warp::serve(get_ip_data).bind(([127, 0, 0, 1], 8000)).await; }