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 } }