Format
This commit is contained in:
parent
45ac24c589
commit
06b34c0e39
|
@ -2,7 +2,7 @@ use flate2::read::GzDecoder;
|
|||
use hyper::net::HttpsConnector;
|
||||
use hyper::{self, Client};
|
||||
use hyper_native_tls::NativeTlsClient;
|
||||
use std::cmp::{Eq, PartialOrd, PartialEq, Ord, Ordering};
|
||||
use std::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
|
||||
use std::collections::Bound::{Included, Unbounded};
|
||||
use std::collections::BTreeSet;
|
||||
use std::io::prelude::*;
|
||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -1,25 +1,25 @@
|
|||
#![cfg_attr(feature="clippy", feature(plugin))]
|
||||
#![cfg_attr(feature="clippy", plugin(clippy))]
|
||||
#![cfg_attr(feature = "clippy", feature(plugin))]
|
||||
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
||||
|
||||
extern crate clap;
|
||||
extern crate flate2;
|
||||
extern crate iron;
|
||||
#[macro_use]
|
||||
extern crate router;
|
||||
#[macro_use]
|
||||
extern crate horrorshow;
|
||||
extern crate hyper;
|
||||
extern crate hyper_native_tls;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate iron;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate router;
|
||||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
|
||||
mod asns;
|
||||
mod webservice;
|
||||
|
||||
use asns::*;
|
||||
use clap::{Arg, App};
|
||||
use clap::{App, Arg};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
@ -48,20 +48,24 @@ fn main() {
|
|||
.version("0.2.0")
|
||||
.author("Frank Denis")
|
||||
.about("Webservice for https://iptoasn.com")
|
||||
.arg(Arg::with_name("listen_addr")
|
||||
.short("l")
|
||||
.long("listen")
|
||||
.value_name("ip:port")
|
||||
.help("Webservice IP and port")
|
||||
.takes_value(true)
|
||||
.default_value("0.0.0.0:53661"))
|
||||
.arg(Arg::with_name("db_url")
|
||||
.short("u")
|
||||
.long("dburl")
|
||||
.value_name("url")
|
||||
.help("URL of the gzipped database")
|
||||
.takes_value(true)
|
||||
.default_value("https://iptoasn.com/data/ip2asn-combined.tsv.gz"))
|
||||
.arg(
|
||||
Arg::with_name("listen_addr")
|
||||
.short("l")
|
||||
.long("listen")
|
||||
.value_name("ip:port")
|
||||
.help("Webservice IP and port")
|
||||
.takes_value(true)
|
||||
.default_value("0.0.0.0:53661"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("db_url")
|
||||
.short("u")
|
||||
.long("dburl")
|
||||
.value_name("url")
|
||||
.help("URL of the gzipped database")
|
||||
.takes_value(true)
|
||||
.default_value("https://iptoasn.com/data/ip2asn-combined.tsv.gz"),
|
||||
)
|
||||
.get_matches();
|
||||
let db_url = matches.value_of("db_url").unwrap().to_owned();
|
||||
let listen_addr = matches.value_of("listen_addr").unwrap();
|
||||
|
@ -69,9 +73,9 @@ fn main() {
|
|||
let asns_arc = Arc::new(RwLock::new(Arc::new(asns)));
|
||||
let asns_arc_copy = asns_arc.clone();
|
||||
thread::spawn(move || loop {
|
||||
thread::sleep(Duration::from_secs(3600));
|
||||
update_asns(&asns_arc_copy, &db_url);
|
||||
});
|
||||
thread::sleep(Duration::from_secs(3600));
|
||||
update_asns(&asns_arc_copy, &db_url);
|
||||
});
|
||||
info!("Starting the webservice");
|
||||
WebService::start(asns_arc, listen_addr);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use asns::*;
|
||||
use horrorshow::prelude::*;
|
||||
use iron::{BeforeMiddleware, typemap};
|
||||
use iron::headers::{CacheControl, CacheDirective, Accept};
|
||||
use iron::{typemap, BeforeMiddleware};
|
||||
use iron::headers::{Accept, CacheControl, CacheDirective};
|
||||
use iron::mime::*;
|
||||
use iron::modifiers::Header;
|
||||
use iron::prelude::*;
|
||||
|
@ -45,13 +45,18 @@ pub struct WebService;
|
|||
|
||||
impl WebService {
|
||||
fn index(_: &mut Request) -> IronResult<Response> {
|
||||
Ok(Response::with((status::Ok,
|
||||
Mime(TopLevel::Text,
|
||||
SubLevel::Plain,
|
||||
vec![(Attr::Charset, Value::Utf8)]),
|
||||
Header(CacheControl(vec![CacheDirective::Public,
|
||||
CacheDirective::MaxAge(TTL)])),
|
||||
"See https://iptoasn.com")))
|
||||
Ok(Response::with((
|
||||
status::Ok,
|
||||
Mime(
|
||||
TopLevel::Text,
|
||||
SubLevel::Plain,
|
||||
vec![(Attr::Charset, Value::Utf8)],
|
||||
),
|
||||
Header(CacheControl(
|
||||
vec![CacheDirective::Public, CacheDirective::MaxAge(TTL)],
|
||||
)),
|
||||
"See https://iptoasn.com",
|
||||
)))
|
||||
}
|
||||
|
||||
fn accept_type(req: &Request) -> OutputType {
|
||||
|
@ -74,22 +79,28 @@ impl WebService {
|
|||
output_type
|
||||
}
|
||||
|
||||
fn output_json(map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>)
|
||||
-> IronResult<Response> {
|
||||
fn output_json(
|
||||
map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>,
|
||||
) -> IronResult<Response> {
|
||||
let json = serde_json::to_string(&map).unwrap();
|
||||
let mime_json = Mime(TopLevel::Application,
|
||||
SubLevel::Json,
|
||||
vec![(Attr::Charset, Value::Utf8)]);
|
||||
let mime_json = Mime(
|
||||
TopLevel::Application,
|
||||
SubLevel::Json,
|
||||
vec![(Attr::Charset, Value::Utf8)],
|
||||
);
|
||||
Ok(Response::with((status::Ok, mime_json, cache_header, json)))
|
||||
}
|
||||
|
||||
fn output_html(map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>)
|
||||
-> IronResult<Response> {
|
||||
let mime_html = Mime(TopLevel::Text,
|
||||
SubLevel::Html,
|
||||
vec![(Attr::Charset, Value::Utf8)]);
|
||||
fn output_html(
|
||||
map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>,
|
||||
) -> IronResult<Response> {
|
||||
let mime_html = Mime(
|
||||
TopLevel::Text,
|
||||
SubLevel::Html,
|
||||
vec![(Attr::Charset, Value::Utf8)],
|
||||
);
|
||||
let html = html!{
|
||||
head {
|
||||
title { : "iptoasn lookup" }
|
||||
|
@ -145,10 +156,11 @@ impl WebService {
|
|||
Ok(Response::with((status::Ok, mime_html, cache_header, html)))
|
||||
}
|
||||
|
||||
fn output(output_type: OutputType,
|
||||
map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>)
|
||||
-> IronResult<Response> {
|
||||
fn output(
|
||||
output_type: OutputType,
|
||||
map: serde_json::Map<String, serde_json::value::Value>,
|
||||
cache_header: Header<CacheControl>,
|
||||
) -> IronResult<Response> {
|
||||
match output_type {
|
||||
OutputType::Json => Self::output_json(map, cache_header),
|
||||
_ => Self::output_html(map, cache_header),
|
||||
|
@ -156,54 +168,77 @@ impl WebService {
|
|||
}
|
||||
|
||||
fn ip_lookup(req: &mut Request) -> IronResult<Response> {
|
||||
let mime_text = Mime(TopLevel::Text,
|
||||
SubLevel::Plain,
|
||||
vec![(Attr::Charset, Value::Utf8)]);
|
||||
let cache_header = Header(CacheControl(vec![CacheDirective::Public,
|
||||
CacheDirective::MaxAge(TTL)]));
|
||||
let mime_text = Mime(
|
||||
TopLevel::Text,
|
||||
SubLevel::Plain,
|
||||
vec![(Attr::Charset, Value::Utf8)],
|
||||
);
|
||||
let cache_header = Header(CacheControl(
|
||||
vec![CacheDirective::Public, CacheDirective::MaxAge(TTL)],
|
||||
));
|
||||
let ip_str = match req.extensions.get::<Router>().unwrap().find("ip") {
|
||||
None => {
|
||||
let response = Response::with((status::BadRequest,
|
||||
mime_text,
|
||||
cache_header,
|
||||
"Missing IP address"));
|
||||
let response = Response::with((
|
||||
status::BadRequest,
|
||||
mime_text,
|
||||
cache_header,
|
||||
"Missing IP address",
|
||||
));
|
||||
return Ok(response);
|
||||
}
|
||||
Some(ip_str) => ip_str,
|
||||
};
|
||||
let ip = match IpAddr::from_str(ip_str) {
|
||||
Err(_) => {
|
||||
return Ok(Response::with((status::BadRequest,
|
||||
mime_text,
|
||||
cache_header,
|
||||
"Invalid IP address")));
|
||||
return Ok(Response::with((
|
||||
status::BadRequest,
|
||||
mime_text,
|
||||
cache_header,
|
||||
"Invalid IP address",
|
||||
)));
|
||||
}
|
||||
Ok(ip) => ip,
|
||||
};
|
||||
let asns = req.extensions.get::<ASNsMiddleware>().unwrap();
|
||||
let mut map = serde_json::Map::new();
|
||||
map.insert("ip".to_string(),
|
||||
serde_json::value::Value::String(ip_str.to_string()));
|
||||
map.insert(
|
||||
"ip".to_string(),
|
||||
serde_json::value::Value::String(ip_str.to_string()),
|
||||
);
|
||||
let found = match asns.lookup_by_ip(ip) {
|
||||
None => {
|
||||
map.insert("announced".to_string(),
|
||||
serde_json::value::Value::Bool(false));
|
||||
map.insert(
|
||||
"announced".to_string(),
|
||||
serde_json::value::Value::Bool(false),
|
||||
);
|
||||
return Self::output(Self::accept_type(&req), map, cache_header);
|
||||
}
|
||||
Some(found) => found,
|
||||
};
|
||||
map.insert("announced".to_string(),
|
||||
serde_json::value::Value::Bool(true));
|
||||
map.insert("first_ip".to_string(),
|
||||
serde_json::value::Value::String(found.first_ip.to_string()));
|
||||
map.insert("last_ip".to_string(),
|
||||
serde_json::value::Value::String(found.last_ip.to_string()));
|
||||
map.insert("as_number".to_string(),
|
||||
serde_json::value::Value::Number(serde_json::Number::from(found.number)));
|
||||
map.insert("as_country_code".to_string(),
|
||||
serde_json::value::Value::String(found.country.clone()));
|
||||
map.insert("as_description".to_string(),
|
||||
serde_json::value::Value::String(found.description.clone()));
|
||||
map.insert(
|
||||
"announced".to_string(),
|
||||
serde_json::value::Value::Bool(true),
|
||||
);
|
||||
map.insert(
|
||||
"first_ip".to_string(),
|
||||
serde_json::value::Value::String(found.first_ip.to_string()),
|
||||
);
|
||||
map.insert(
|
||||
"last_ip".to_string(),
|
||||
serde_json::value::Value::String(found.last_ip.to_string()),
|
||||
);
|
||||
map.insert(
|
||||
"as_number".to_string(),
|
||||
serde_json::value::Value::Number(serde_json::Number::from(found.number)),
|
||||
);
|
||||
map.insert(
|
||||
"as_country_code".to_string(),
|
||||
serde_json::value::Value::String(found.country.clone()),
|
||||
);
|
||||
map.insert(
|
||||
"as_description".to_string(),
|
||||
serde_json::value::Value::String(found.description.clone()),
|
||||
);
|
||||
Self::output(Self::accept_type(&req), map, cache_header)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue