diff --git a/src/http/mod.rs b/src/http/mod.rs index 6fdc7fb..f81a18f 100644 --- a/src/http/mod.rs +++ b/src/http/mod.rs @@ -100,30 +100,38 @@ pub struct Status { } impl Status { - pub fn from_code(status_code: u16) -> Status { + pub fn from_code(status_code: u16) -> Option { for (code, class, msg, desc) in &consts::HTTP_STATUSES { if *code == status_code { - return Status { + return Some(Status { code: status_code, message: msg.to_string(), desc, class: class.clone(), - }; + }); } } - panic!("invalid status code"); + None } pub fn new_custom(status_code: u16, message: &str) -> Status { if status_code < 100 || status_code > 599 { panic!("invalid status code"); } - let status = Status::from_code(status_code); - Status { - code: status_code, - message: message.to_string(), - desc: status.desc, - class: status.class, + if let Some(status) = Status::from_code(status_code) { + Status { + code: status_code, + message: message.to_string(), + desc: status.desc, + class: status.class, + } + } else { + Status { + code: status_code, + message: message.to_string(), + desc: "", + class: StatusClass::from_code(status_code), + } } } } @@ -156,13 +164,13 @@ impl Response { pub fn new() -> Response { Response { version: "1.1".to_string(), - status: Status::from_code(200), + status: Status::from_code(200).unwrap(), header_fields: Vec::new(), } } pub fn status(&mut self, status_code: u16) { - self.status = Status::from_code(status_code) + self.status = Status::from_code(status_code).unwrap() } pub fn add_header(&mut self, name: &str, value: &str) { @@ -197,33 +205,11 @@ impl Response { let mut buf = None; if let None = self.find_header("Content-Length") { - let (doc, color_name, color) = match self.status.class { - StatusClass::Informational => (consts::INFO_DOCUMENT, "info", "#606060"), - StatusClass::Success => (consts::SUCCESS_DOCUMENT, "success", "#008000"), - StatusClass::Redirection => (consts::WARNING_DOCUMENT, "warning", "#E0C000"), - StatusClass::ClientError => (consts::ERROR_DOCUMENT, "error", "#C00000"), - StatusClass::ServerError => (consts::ERROR_DOCUMENT, "error", "#C00000"), - }; - - let new_buf = consts::DEFAULT_DOCUMENT - .replace("{status_code}", self.status.code.to_string().as_str()) - .replace("{status_message}", self.status.message.as_str()) - .replace("{hostname}", "localhost") // TODO hostname - .replace("{theme_color}", color) - .replace("{color_name}", color_name) - .replace("{server_str}", "Locutus server") // TODO server string - .replace( - "{doc}", - doc.replace("{code}", self.status.code.to_string().as_str()) - .replace("{message}", self.status.message.as_str()) - .replace("{desc}", self.status.desc) - .replace("{info}", "") // TODO info string - .as_str(), - ) - .replace("{{", "{") - .replace("}}", "}"); - - self.add_header("Content-Length", new_buf.len().to_string().as_str()); + let new_buf = self.format_default_response(); + self.add_header( + "Content-Length", + new_buf.as_bytes().len().to_string().as_str(), + ); self.add_header("Content-Type", "text/html; charset=utf-8"); buf = Some(new_buf); } @@ -243,6 +229,34 @@ impl Response { } Ok(()) } + + fn format_default_response(&self) -> String { + let (doc, color_name, color) = match self.status.class { + StatusClass::Informational => (consts::INFO_DOCUMENT, "info", "#606060"), + StatusClass::Success => (consts::SUCCESS_DOCUMENT, "success", "#008000"), + StatusClass::Redirection => (consts::WARNING_DOCUMENT, "warning", "#E0C000"), + StatusClass::ClientError => (consts::ERROR_DOCUMENT, "error", "#C00000"), + StatusClass::ServerError => (consts::ERROR_DOCUMENT, "error", "#C00000"), + }; + + consts::DEFAULT_DOCUMENT + .replace("{status_code}", self.status.code.to_string().as_str()) + .replace("{status_message}", self.status.message.as_str()) + .replace("{hostname}", "localhost") // TODO hostname + .replace("{theme_color}", color) + .replace("{color_name}", color_name) + .replace("{server_str}", "Locutus server") // TODO server string + .replace( + "{doc}", + doc.replace("{code}", self.status.code.to_string().as_str()) + .replace("{message}", self.status.message.as_str()) + .replace("{desc}", self.status.desc) + .replace("{info}", "") // TODO info string + .as_str(), + ) + .replace("{{", "{") + .replace("}}", "}") + } } impl Stream {