mini_async_http/request/
request.rs1use crate::http::parser::BuildError;
2use crate::http::Headers;
3use crate::http::Method;
4use crate::http::Version;
5
6use std::convert::TryFrom;
7use std::fmt;
8
9#[derive(Debug, PartialEq)]
11pub struct Request {
12 method: Method,
13 path: String,
14 version: Version,
15 headers: Headers,
16 body: Option<Vec<u8>>,
17}
18
19impl Request {
20 pub fn method(&self) -> &Method {
22 &self.method
23 }
24
25 pub fn path(&self) -> &String {
27 &self.path
28 }
29
30 pub fn version(&self) -> &Version {
32 &self.version
33 }
34
35 pub fn headers(&self) -> &Headers {
37 &self.headers
38 }
39
40 pub fn body(&self) -> Option<&Vec<u8>> {
42 self.body.as_ref()
43 }
44
45 pub fn body_as_string(&self) -> Option<String> {
47 match self.body.as_ref() {
48 Some(val) => match String::from_utf8(val.to_vec()) {
49 Ok(body) => Some(body),
50 Err(_) => None,
51 },
52 None => None,
53 }
54 }
55}
56
57impl fmt::Display for Request {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 let mut buf = String::new();
60
61 buf.push_str(
62 format!(
63 "{} {} {}\r\n",
64 self.method.as_str(),
65 self.path,
66 self.version.as_str()
67 )
68 .as_str(),
69 );
70
71 self.headers
72 .iter()
73 .for_each(|(key, value)| buf.push_str(format!("{}: {}\r\n", key, value).as_str()));
74
75 buf.push_str("\r\n");
76
77 match &self.body_as_string() {
78 Some(body) => buf.push_str(body.as_str()),
79 None => {}
80 };
81
82 write!(f, "{}", buf)
83 }
84}
85
86impl TryFrom<&[u8]> for Request {
87 type Error = crate::http::parser::ParseError;
88
89 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
90 let parser = crate::request::request_parser::RequestParser::new();
91
92 match parser.parse_u8(slice) {
93 Ok((request, _)) => Ok(request),
94 Err(e) => Err(e),
95 }
96 }
97}
98
99pub struct RequestBuilder {
101 method: Option<Method>,
102 path: Option<String>,
103 version: Option<Version>,
104 headers: Headers,
105 body: Option<Vec<u8>>,
106}
107
108impl RequestBuilder {
109 pub fn new() -> RequestBuilder {
110 RequestBuilder {
111 method: Option::None,
112 path: Option::None,
113 version: Option::None,
114 headers: Headers::new(),
115 body: Option::None,
116 }
117 }
118
119 pub fn method(mut self, method: Method) -> Self {
121 self.method = Option::Some(method);
122 self
123 }
124
125 pub fn path(mut self, path: String) -> Self {
127 self.path = Option::Some(path);
128 self
129 }
130
131 pub fn version(mut self, version: Version) -> Self {
133 self.version = Option::Some(version);
134 self
135 }
136
137 pub fn headers(mut self, headers: Headers) -> Self {
139 self.headers = headers;
140 self
141 }
142
143 pub fn body(mut self, body: &[u8]) -> Self {
145 self.body = Option::Some(body.to_vec());
146 self
147 }
148
149 pub fn build(self) -> Result<Request, BuildError> {
152 let method = match self.method {
153 Some(val) => val,
154 None => return Result::Err(BuildError::Incomplete),
155 };
156
157 let path = match self.path {
158 Some(val) => val,
159 None => return Result::Err(BuildError::Incomplete),
160 };
161
162 let version = match self.version {
163 Some(val) => val,
164 None => return Result::Err(BuildError::Incomplete),
165 };
166
167 Result::Ok(Request {
168 method,
169 path,
170 version,
171 headers: self.headers,
172 body: self.body,
173 })
174 }
175}
176
177impl Default for RequestBuilder {
178 fn default() -> Self {
179 RequestBuilder::new()
180 }
181}