From 73a2748806fd20846156eca928be4667f263be0f Mon Sep 17 00:00:00 2001 From: dqnid Date: Thu, 16 Jan 2025 20:42:46 +0100 Subject: [PATCH] feat: new format response in order to properly manage headers --- docs/TODO.md | 4 +++ src/http/generators.rs | 26 +++++++++++++++++++ src/http/server.rs | 58 ++++++++++++++++++++++-------------------- src/http/types.rs | 13 ++++++++-- 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/docs/TODO.md b/docs/TODO.md index c23ac0b..e64b6b1 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -1,4 +1,5 @@ # TODO + - [x] Manage requests - [x] Router - [NOT NEEDED] HTTP code mapper : not needed because a code will be directly translated on the client (browser / postman) @@ -9,7 +10,10 @@ - [ ] Auto-cleanup - [ ] Transversal utility - [ ] Let programmer set the default not found response +- [x] Manage basic defaults app and route headers +- [ ] Manage route specific headers - [ ] Allow middleware +- [ ] Study how to organize functions on structs or types if possible ## Improvements diff --git a/src/http/generators.rs b/src/http/generators.rs index 0763a41..a5f8790 100644 --- a/src/http/generators.rs +++ b/src/http/generators.rs @@ -1,3 +1,29 @@ use super::*; // pub fn generate_response(petition: HttpRequest) -> ProcessedResponse {} + +fn format_response_headers(headers: Headers, content_len: usize, content_type: &str) -> String { + let mut response_headers = String::new(); + response_headers.push_str(format!("Content-Length: {}", content_len).as_str()); + response_headers.push_str(format!("\nContent-Type: {}", content_type).as_str()); + for (key, value) in headers { + response_headers.push_str(format!("\n{key}: {value}").as_str()); + } + return response_headers; +} + +pub fn format_response(raw_response: HttpAppRouteResponse) -> ProcessedResponse { + ProcessedResponse { + data: format!( + "HTTP/1.1 {}\r\n{}\r\n\r\n{}", + raw_response.status, + format_response_headers( + raw_response.headers, + raw_response.body.len(), + raw_response.content_type + ), + raw_response.body + ), + status: raw_response.status, + } +} diff --git a/src/http/server.rs b/src/http/server.rs index 6126300..b56f436 100644 --- a/src/http/server.rs +++ b/src/http/server.rs @@ -1,10 +1,29 @@ -use std::fs; +use std::collections::HashMap; use std::io::prelude::*; use std::net::{SocketAddr, TcpListener, TcpStream}; use super::*; -impl HttpApp { +impl Default for HttpAppConfig { + fn default() -> Self { + Self { + port: 3000, + max_buffer_size_bytes: 5120, + } + } +} + +impl Default for HttpApp<'_> { + fn default() -> Self { + Self { + config: Default::default(), + routes: vec![], + default_headers: HashMap::new(), + } + } +} + +impl HttpApp<'_> { fn get_route(&self, _path: &str) -> Option<&HttpAppRoute> { self.routes.first() // TODO: search the real one } @@ -21,37 +40,22 @@ impl HttpApp { match petition { Ok(petition_parsed) => { - let response_status = "200 OK"; - // let mut response_content = fs::read_to_string("./routes/index.html").unwrap(); - let mut response_content = "".to_string(); - if let Some(route) = self.get_route(petition_parsed.request.query.path) { - response_content = (route.action)(petition_parsed); + let matched_route = (route.action)(petition_parsed); + return format_response(matched_route); } else { // TODO: return not found + return ProcessedResponse { + data: "".to_string(), + status: 400, + }; } - - let response: ProcessedResponse = ProcessedResponse { - data: format!( - "HTTP/1.1 {}\r\nContent-Length: {}\r\n\r\n{}", - response_status, - response_content.len(), - response_content - ), - status: 200, - }; - - response - } - Err(error) => { - let response: ProcessedResponse = ProcessedResponse { - data: format!("HTTP/1.1 {}\r\nContent-Length: 0\r\n\r\n", error), - status: error, - }; - - response } + Err(error) => ProcessedResponse { + data: format!("HTTP/1.1 {}\r\nContent-Length: 0\r\n\r\n", error), + status: error, + }, } } diff --git a/src/http/types.rs b/src/http/types.rs index 88c3904..1ff9fd6 100644 --- a/src/http/types.rs +++ b/src/http/types.rs @@ -5,18 +5,27 @@ use std::collections::HashMap; * */ pub struct HttpAppConfig { pub port: u16, + pub max_buffer_size_bytes: usize, } -pub type HttpAppRouteFunction = Box String>; +pub type HttpAppRouteFunction = Box HttpAppRouteResponse>; pub struct HttpAppRoute { pub route: String, pub action: HttpAppRouteFunction, } -pub struct HttpApp { +pub struct HttpApp<'a> { pub config: HttpAppConfig, pub routes: Vec, + pub default_headers: Headers<'a>, +} + +pub struct HttpAppRouteResponse<'a> { + pub body: String, + pub content_type: &'a str, + pub status: Status, + pub headers: Headers<'a>, } /*