diff --git a/docker/build-linux.bat b/docker/build-linux.bat index a52d538..e17e8a4 100644 --- a/docker/build-linux.bat +++ b/docker/build-linux.bat @@ -8,4 +8,4 @@ docker run --rm ^ -v "%cd%\docker\linux\cargo":/tmp/cargo ^ -w /usr/src/rsddns ^ rust:1.30.1-stretch ^ -cargo build --release && strip $/usr/src/rsddns/target/release/rsddns \ No newline at end of file +cargo build --release && strip /usr/src/rsddns/target/release/rsddns \ No newline at end of file diff --git a/src/server/api.rs b/src/server/api.rs index 5c5a6ef..04c3439 100644 --- a/src/server/api.rs +++ b/src/server/api.rs @@ -1,4 +1,6 @@ use std::io::Read; +use std::net::IpAddr; +use std::str::FromStr; use actix_web::{AsyncResponder, FutureResponse, HttpMessage, HttpRequest, HttpResponse, Scope}; use actix_web::http::Method; @@ -6,6 +8,8 @@ use actix_web::http::StatusCode; use bytes::{Buf, Bytes, IntoBuf}; use futures::future::Future; +use server::error::APIError; + pub fn route(scope: Scope<()>) -> Scope<()> { scope.resource("address", |r| r.method(Method::GET).f(get_address)) .nested("{root}/{zone}", |zone_scope| { @@ -23,20 +27,53 @@ fn update_address(address: String) -> String { address } +fn parse_remote_info(remote_info: &str) -> Result { + let mut remote_address = String::from(remote_info); + if remote_address.contains(":") { + let last_colon_index = remote_address.rfind(":").unwrap(); + let port = remote_address.split_off(last_colon_index); + if remote_address.starts_with("[") && remote_address.ends_with("]") { + remote_address = String::from(remote_address.trim_matches(|c| c == '[' || c == ']')) + } + match IpAddr::from_str(&remote_address) { + Ok(v) => Ok(v), + Err(e) => Err(APIError::new(&format!("Address Parse Error \"{}\"", remote_address), Some(Box::from(e)))) + } + } else { + Err(APIError::new(&format!("{} could not be parsed", remote_address), None)) + } +} + fn get_address(req: &HttpRequest) -> HttpResponse { match req.connection_info().remote() { - Some(addr) => HttpResponse::build(StatusCode::OK) - .content_type("text/plain") - .body(format!("{}", addr)), + Some(remote_info) => { + match parse_remote_info(remote_info) { + Ok(addr) => HttpResponse::build(StatusCode::OK) + .content_type("text/plain") + .body(format!("{}", addr)), + Err(e) => { + error!("{}", e); + HttpResponse::build(StatusCode::BAD_REQUEST).finish() + } + } + } None => HttpResponse::build(StatusCode::BAD_REQUEST).finish(), } } fn update_address_automatically(req: &HttpRequest) -> HttpResponse { match req.connection_info().remote() { - Some(addr) => HttpResponse::build(StatusCode::OK) - .content_type("text/plain") - .body(format!("{}", addr)), + Some(remote_info) => { + match parse_remote_info(remote_info) { + Ok(addr) => HttpResponse::build(StatusCode::OK) + .content_type("text/plain") + .body(format!("{}", addr)), + Err(e) => { + error!("{}", e); + HttpResponse::build(StatusCode::BAD_REQUEST).finish() + } + } + } None => HttpResponse::build(StatusCode::BAD_REQUEST).finish(), } } diff --git a/src/server/error.rs b/src/server/error.rs new file mode 100644 index 0000000..2c78044 --- /dev/null +++ b/src/server/error.rs @@ -0,0 +1,30 @@ +use std::error::Error; +use std::fmt; + +#[derive(Debug)] +pub struct APIError { + description: String, + original_error: Option>, +} + +impl APIError { + pub fn new(description: &str, original_error: Option>) -> APIError { + APIError { + description: String::from(description), + original_error, + } + } +} + +impl Error for APIError {} + +impl fmt::Display for APIError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match &self.original_error { + Some(original_error) => { + write!(f, "{}: \"{}\"", self.description, original_error) + } + None => write!(f, "{}", self.description) + } + } +} \ No newline at end of file diff --git a/src/server/mod.rs b/src/server/mod.rs index 1e621b0..a369eef 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -3,6 +3,7 @@ use actix_web::{HttpRequest, Json, Result}; use VERSION; pub mod api; +pub mod error; pub mod router; #[derive(Serialize)]