diff options
Diffstat (limited to 'src/request.rs')
-rw-r--r-- | src/request.rs | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/request.rs b/src/request.rs new file mode 100644 index 0000000..f337556 --- /dev/null +++ b/src/request.rs @@ -0,0 +1,85 @@ +use std::str::FromStr; +use crate::{version::Version, method::Method, uri::URI, header::{HeaderMap, Header}, error::HTTPError, parse::TryParse}; + +pub struct Request<T: ToString + FromStr> { + pub method: Method, + pub uri: URI, + pub version: Version, + pub headers: HeaderMap, + pub body: Option<T> +} + +impl<T: ToString + FromStr> TryParse for Request<T> { + fn try_parse(s: impl Into<String>) -> Result<Self, HTTPError> { + let s = s.into(); + let mut lines = s.lines(); + let Some(head) = lines.next() else { + return Err(HTTPError::MissingHeader) + }; + + let mut head_parts = head.split_whitespace(); + let err = HTTPError::InvalidHeader(s.clone()); + + let Some(method_str) = head_parts.next() else { return Err(err) }; + let method = method_str.into(); + + let Some(uri_str) = head_parts.next() else { return Err(err) }; + let uri = uri_str.try_into()?; + + let Some(version_str) = head_parts.next() else { return Err(err) }; + let version = version_str.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 { method, uri, version, headers, body }) + } +} + +impl<T: ToString + FromStr> ToString for Request<T> { + fn to_string(&self) -> String { + let mut s = String::new(); + + s.push_str(&self.method.as_str()); + s.push(' '); + s.push_str(&self.uri.to_string()); + s.push(' '); + s.push_str(self.version.as_str()); + 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 + } +} |