improve HTTPResponse to include custom HTTPMessage

This commit is contained in:
landrigun 2022-10-13 12:20:30 +00:00
parent 808cd3ee77
commit 7073a4b88e
5 changed files with 70 additions and 21 deletions

View File

@ -33,10 +33,27 @@ impl TryInto<json::JsonValue> for HTTPMessage {
} }
impl 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()); self.message.insert(key.to_string(), value.to_string());
} }
/// associated function to build an HTTPMessage error
pub fn error(message: &str) -> Option<json::JsonValue> {
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` /// 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 { fn build_json(self) -> String {
let unstruct: Vec<String> = self let unstruct: Vec<String> = self

View File

@ -6,6 +6,6 @@ pub mod response;
pub mod router; pub mod router;
pub use message::HTTPMessage; pub use message::HTTPMessage;
pub use request::HTTPRequest; pub use request::{HTTPRequest, HTTPVersion};
pub use response::{HTTPResponse, HTTPStatusCode}; pub use response::{HTTPResponse, HTTPStatusCode};
pub use router::ROUTER; pub use router::ROUTER;

View File

@ -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 //! 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 //! NOTE: only few parts of the specification has been implemented
use crate::http::request::HTTPVersion; use super::{HTTPMessage, HTTPVersion};
use json; use json;
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
@ -92,13 +92,19 @@ impl Into<String> for HTTPResponse {
} }
impl HTTPResponse { impl HTTPResponse {
pub fn as_500() -> Self { pub fn as_500(message: Option<json::JsonValue>) -> Self {
let mut response = Self::default(); let mut response = Self::default();
response response
.status_line .status_line
.set_status_code(HTTPStatusCode::Http500); .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 response
} }
@ -119,9 +125,11 @@ impl HTTPResponse {
status_line: HTTPStatusLine::default(), status_line: HTTPStatusLine::default(),
body: json::parse(r#"{"error": "invalid credentials"}"#).unwrap(), body: json::parse(r#"{"error": "invalid credentials"}"#).unwrap(),
}; };
response response
.status_line .status_line
.set_status_code(HTTPStatusCode::Http403); .set_status_code(HTTPStatusCode::Http403);
response response
} }
@ -130,16 +138,35 @@ impl HTTPResponse {
Self::default() Self::default()
} }
// TODO: need to be adjust to accept `json::JsonValue` pub fn as_200(message: Option<json::JsonValue>) -> Self {
pub fn as_200(token: String) -> Self {
let mut response = Self::default(); let mut response = Self::default();
response response
.status_line .status_line
.set_status_code(HTTPStatusCode::Http200); .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 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))
}
} }

View File

@ -1,7 +1,7 @@
//! router aims to handle correctly the request corresponding to the target //! router aims to handle correctly the request corresponding to the target
//! it implements all the logic to build an `HTTPResponse` //! it implements all the logic to build an `HTTPResponse`
use super::{HTTPRequest, HTTPResponse}; use super::{HTTPMessage, HTTPRequest, HTTPResponse};
use crate::config::Config; use crate::config::Config;
use crate::stores::FileStore; use crate::stores::FileStore;
use crate::stores::Store; use crate::stores::Store;
@ -36,10 +36,11 @@ fn handle_get(request: HTTPRequest, config: Config) -> FuturePinned<HTTPResponse
let jwt_key = { let jwt_key = {
match RS384KeyPair::from_pem(priv_key_content.as_str()) { match RS384KeyPair::from_pem(priv_key_content.as_str()) {
Ok(k) => k, Ok(k) => k,
// TODO: set error in the message body
Err(e) => { Err(e) => {
eprintln!("error occurred while getting private key err={}", e); let message: Option<json::JsonValue> = HTTPMessage::error(
return HTTPResponse::as_500(); 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
claims.issuer = Some(config.jwt_issuer); claims.issuer = Some(config.jwt_issuer);
match jwt_key.sign(claims) { match jwt_key.sign(claims) {
Ok(token) => HTTPResponse::as_200(token), Ok(token) => HTTPResponse::send_token(&token),
// TODO: set the error in the message body
Err(e) => { Err(e) => {
eprintln!("error occurred while signing the token err={}", e); let message: Option<json::JsonValue> = HTTPMessage::error(
return HTTPResponse::as_500(); 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<HTTPRe
match &request.body { match &request.body {
Some(ref _b) => { Some(ref _b) => {
// TODO: impl the JWT validation // TODO: impl the JWT validation
HTTPResponse::as_200("header.payload.signature".to_string()) HTTPResponse::send_token("header.payload.signature")
} }
None => HTTPResponse::as_400(), None => HTTPResponse::as_400(),
} }

View File

@ -46,10 +46,13 @@ async fn main() {
} }
}; };
let router_config: Config = if let Ok(c) = Config::try_from(config) { let router_config: Config = {
c match Config::try_from(config) {
} else { Ok(c) => c,
Err(_e) => {
std::process::exit(1); std::process::exit(1);
}
}
}; };
loop { loop {