Parse ip2asn data
parent
33674eec78
commit
9656d070b6
|
@ -0,0 +1,12 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = true
|
||||
|
||||
[*.rs]
|
||||
indent_size = 4
|
|
@ -75,6 +75,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -147,6 +153,7 @@ dependencies = [
|
|||
name = "geoip-api"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"tokio",
|
||||
"warp",
|
||||
]
|
||||
|
@ -309,6 +316,15 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.8"
|
||||
|
|
|
@ -5,5 +5,6 @@ edition = "2021"
|
|||
authors = ["charlotte ✨ <charlotte@lavender.software>"]
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.10.3"
|
||||
tokio = { version = "1.15.0", features = ["full"] }
|
||||
warp = "0.3.2"
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# geoip-api
|
||||
|
||||
HTTP API for converting an IPv4 address to a country code.
|
||||
|
||||
Uses the [`iptoasn.com`](https://iptoasn.com) dataset.
|
||||
|
||||
## Setup
|
||||
|
||||
Grab the latest `ip2asn-v4.tsv.gz` and extract it to `data/ip2asn-v4.tsv`.
|
||||
|
||||
Then just use `cargo` as usual.
|
||||
|
||||
## Usage
|
||||
|
||||
```shell
|
||||
$ http GET 'http://127.0.0.1:8000/192.168.0.1'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"asn": 0,
|
||||
"country_code": "None",
|
||||
"asn_desc": "Not routed"
|
||||
}
|
||||
```
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
43
src/main.rs
43
src/main.rs
|
@ -1,7 +1,50 @@
|
|||
use itertools::Itertools;
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
|
||||
use warp::Filter;
|
||||
|
||||
const IP2ASN_DATA: &str = include_str!("../data/ip2asn-v4.tsv");
|
||||
|
||||
#[derive(Debug)]
|
||||
struct RangeRecord {
|
||||
ip_start: Ipv4Addr,
|
||||
ip_end: Ipv4Addr,
|
||||
asn: u64,
|
||||
country_code: &'static str,
|
||||
asn_description: &'static str,
|
||||
}
|
||||
|
||||
fn parse_ranges() -> Vec<RangeRecord> {
|
||||
let mut ranges = Vec::with_capacity(IP2ASN_DATA.lines().count());
|
||||
|
||||
IP2ASN_DATA
|
||||
.lines()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|l| {
|
||||
l.splitn(5, '\t')
|
||||
.next_tuple::<(&str, &str, &str, &str, &str)>()
|
||||
.unwrap()
|
||||
})
|
||||
.for_each(|(ip_start, ip_end, asn, country_code, asn_description)| {
|
||||
ranges.push(RangeRecord {
|
||||
ip_start: ip_start.parse().unwrap(),
|
||||
ip_end: ip_end.parse().unwrap(),
|
||||
asn: asn.parse().unwrap(),
|
||||
country_code,
|
||||
asn_description,
|
||||
})
|
||||
});
|
||||
|
||||
ranges
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
eprintln!("[i] Parsing IP ASN data...");
|
||||
let _ranges = Arc::new(parse_ranges());
|
||||
eprintln!("[i] Done!");
|
||||
|
||||
let hello = warp::any().map(|| "Hello!".to_string());
|
||||
println!("\nListening on http://127.0.0.1:8000 ...");
|
||||
warp::serve(hello).bind(([127, 0, 0, 1], 8000)).await;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue