From 168b8937eb0fe88311fe474ab9569691a19d087f Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 5 Jul 2023 21:34:20 -0400 Subject: changes --- src/response.rs | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/response.rs (limited to 'src/response.rs') diff --git a/src/response.rs b/src/response.rs new file mode 100644 index 0000000..7f6f326 --- /dev/null +++ b/src/response.rs @@ -0,0 +1,111 @@ +use std::str::FromStr; +use crate::{status::{Status, self}, version::Version, header::{HeaderMap, Header}, parse::TryParse, error::HTTPError}; + +pub struct Response { + version: Version, + status: Status, + headers: HeaderMap, + body: Option +} + +impl Response { + pub fn new() -> Self { + Self { + version: Version::HTTP11, + status: status::SUCCESS, + headers: HeaderMap::new(), + body: None + } + } + + pub fn set_version(mut self, version: impl Into) -> Self { + self.version = version.into(); + self + } + + pub fn set_status(mut self, status: impl Into) -> Self { + self.status = status.into(); + self + } + + pub fn add_header(mut self, header: impl Into
) -> Self { + self.headers.insert(header.into()); + self + } + + pub fn set_body(mut self, body: T) -> Self { + self.body = Some(body); + self + } +} + +impl TryParse for Response { + fn try_parse(s: impl Into) -> Result { + let s = s.into(); + let mut lines = s.lines(); + + let Some(header_str) = lines.next() else { + return Err(HTTPError::MissingHeader) + }; + + let mut header_parts = header_str.split(" "); + let Some(version_str) = header_parts.next() else { + return Err(HTTPError::InvalidHeader(header_str.into())) + }; + let version = version_str.into(); + + let status_str: String = header_parts.collect(); + let status = status_str.try_into()?; + + let mut headers = HeaderMap::new(); + + loop { + let Some(next) = lines.next() else { + return Err(HTTPError::MissingHeaderBreak) + }; + + if next.len() < 1 { break } + + let header = Header::try_parse(next)?; + headers.insert(header); + } + + let rest: String = lines.collect(); + let body; + if rest.len() < 1 { + body = None + } else { + body = match T::from_str(&rest) { + Ok(body) => Some(body), + Err(_) => return Err(HTTPError::InvalidBody) + } + } + + Ok(Self { version, status, headers, body }) + } +} + +impl ToString for Response { + fn to_string(&self) -> String { + let mut s = String::new(); + s.push_str(self.version.as_str()); + s.push(' '); + s.push_str(&self.status.to_string()); + s.push_str("\r\n"); + let iter = self.headers.iter(); + for headers in iter { + for header in headers { + s.push_str(header.name.as_str()); + s.push_str(": "); + s.push_str(header.value.as_str()); + s.push_str("\r\n"); + } + } + s.push_str("\r\n"); + if let Some(body) = &self.body { + s.push_str(&body.to_string()); + } + s + } +} + -- cgit v1.2.3-freya