diff --git a/src/http/message.rs b/src/http/message.rs index 58f8c4f..6e786c7 100644 --- a/src/http/message.rs +++ b/src/http/message.rs @@ -33,10 +33,27 @@ impl TryInto for HTTPMessage { } impl HTTPMessage { - fn put(&mut self, key: &str, value: &str) { + pub fn put(&mut self, key: &str, value: &str) { self.message.insert(key.to_string(), value.to_string()); } + /// associated function to build an HTTPMessage error + pub fn error(message: &str) -> Option { + let mut http_message = HTTPMessage::default(); + http_message.put("error", message); + + match message.try_into() { + Ok(m) => Some(m), + Err(e) => { + eprintln!( + "unable to parse the message: {} into JSON, err={}", + message, e + ); + return None; + } + } + } + /// loops over all the HashMap keys, builds a JSON key value for each one and join them with `JSON_DELIMITER` fn build_json(self) -> String { let unstruct: Vec = self diff --git a/src/http/mod.rs b/src/http/mod.rs index 8431d8f..077d5b4 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -6,6 +6,6 @@ pub mod response; pub mod router; pub use message::HTTPMessage; -pub use request::HTTPRequest; +pub use request::{HTTPRequest, HTTPVersion}; pub use response::{HTTPResponse, HTTPStatusCode}; pub use router::ROUTER; diff --git a/src/http/response.rs b/src/http/response.rs index fcf7fc0..42283d2 100644 --- a/src/http/response.rs +++ b/src/http/response.rs @@ -2,7 +2,7 @@ //! it will build an HTTPResponse corresponding to the HTTP message specs. see: https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages //! NOTE: only few parts of the specification has been implemented -use crate::http::request::HTTPVersion; +use super::{HTTPMessage, HTTPVersion}; use json; #[derive(Debug, PartialEq, Clone)] @@ -92,13 +92,19 @@ impl Into for HTTPResponse { } impl HTTPResponse { - pub fn as_500() -> Self { + pub fn as_500(message: Option) -> Self { let mut response = Self::default(); response .status_line .set_status_code(HTTPStatusCode::Http500); - response.body = json::parse(r#"{"error": "unexpected error occurred"}"#).unwrap(); + + response.body = { + match message { + Some(m) => m, + None => json::parse(r#"{"error": "unexpected error occurred"}"#).unwrap(), + } + }; response } @@ -119,9 +125,11 @@ impl HTTPResponse { status_line: HTTPStatusLine::default(), body: json::parse(r#"{"error": "invalid credentials"}"#).unwrap(), }; + response .status_line .set_status_code(HTTPStatusCode::Http403); + response } @@ -130,16 +138,35 @@ impl HTTPResponse { Self::default() } - // TODO: need to be adjust to accept `json::JsonValue` - pub fn as_200(token: String) -> Self { + pub fn as_200(message: Option) -> Self { let mut response = Self::default(); response .status_line .set_status_code(HTTPStatusCode::Http200); - response.body = json::parse(format!(r#"{{"token": "{}"}}"#, token).as_str()).unwrap(); + response.body = { + match message { + Some(m) => m, + None => json::parse(r#"{"status": "ok"}"#).unwrap(), + } + }; response } + + /// build and HTTP 200 response with the generated JWT + pub fn send_token(token: &str) -> Self { + let mut http_message = HTTPMessage::default(); + http_message.put("token", token); + + let message = { + match http_message.try_into() { + Ok(m) => m, + Err(_e) => json::parse(r#"{"token": "error.generation.token"}"#).unwrap(), + } + }; + + HTTPResponse::as_200(Some(message)) + } } diff --git a/src/http/router.rs b/src/http/router.rs index f2a2089..f89a9b0 100644 --- a/src/http/router.rs +++ b/src/http/router.rs @@ -1,7 +1,7 @@ //! router aims to handle correctly the request corresponding to the target //! it implements all the logic to build an `HTTPResponse` -use super::{HTTPRequest, HTTPResponse}; +use super::{HTTPMessage, HTTPRequest, HTTPResponse}; use crate::config::Config; use crate::stores::FileStore; use crate::stores::Store; @@ -36,10 +36,11 @@ fn handle_get(request: HTTPRequest, config: Config) -> FuturePinned k, - // TODO: set error in the message body Err(e) => { - eprintln!("error occurred while getting private key err={}", e); - return HTTPResponse::as_500(); + let message: Option = HTTPMessage::error( + format!("unable to load the private key, err={}", e).as_str(), + ); + return HTTPResponse::as_500(message); } } }; @@ -47,11 +48,12 @@ fn handle_get(request: HTTPRequest, config: Config) -> FuturePinned HTTPResponse::as_200(token), - // TODO: set the error in the message body + Ok(token) => HTTPResponse::send_token(&token), Err(e) => { - eprintln!("error occurred while signing the token err={}", e); - return HTTPResponse::as_500(); + let message: Option = HTTPMessage::error( + format!("unable to sign the token, err={}", e).as_str(), + ); + return HTTPResponse::as_500(message); } } } @@ -67,7 +69,7 @@ fn handle_validate(request: HTTPRequest, _config: Config) -> FuturePinned { // TODO: impl the JWT validation - HTTPResponse::as_200("header.payload.signature".to_string()) + HTTPResponse::send_token("header.payload.signature") } None => HTTPResponse::as_400(), } diff --git a/src/main.rs b/src/main.rs index 1fb6aae..62c72ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,10 +46,13 @@ async fn main() { } }; - let router_config: Config = if let Ok(c) = Config::try_from(config) { - c - } else { - std::process::exit(1); + let router_config: Config = { + match Config::try_from(config) { + Ok(c) => c, + Err(_e) => { + std::process::exit(1); + } + } }; loop {