http_protocol/request/
mod.rs1use crate::{Body, Headers, HttpVersion, Method, RequestUri};
2use bytes::{BufMut, Bytes, BytesMut};
3use std::error::Error;
4use std::fmt;
5use std::ops::Add;
6
7#[derive(Debug, Clone)]
8pub enum RequestError {
9 MethodIsNone,
10 RequestUriIsNone,
11 HttpVersionIsNone,
12 HeadersIsNone,
13 BodyIsNone,
14 InvalidRequestLine,
15 InvalidHeader,
16 InvalidHeaderValue,
17}
18
19impl fmt::Display for RequestError {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 match self {
22 RequestError::MethodIsNone => write!(f, "Method is None."),
23 RequestError::RequestUriIsNone => write!(f, "Request URI is None."),
24 RequestError::HttpVersionIsNone => write!(f, "HTTP version is None."),
25 RequestError::HeadersIsNone => write!(f, "Headers is None."),
26 RequestError::BodyIsNone => write!(f, "Body is None."),
27 RequestError::InvalidRequestLine => write!(f, "Invalid request line."),
28 RequestError::InvalidHeader => write!(f, "Invalid header."),
29 RequestError::InvalidHeaderValue => write!(f, "Invalid header value."),
30 }
31 }
32}
33
34impl Error for RequestError {}
35
36#[derive(Debug, Clone, Eq, PartialEq)]
37pub struct RequestBuilder {
38 pub method: Option<Method>,
39 pub request_uri: Option<RequestUri>,
40 pub http_version: Option<HttpVersion>,
41 pub headers: Option<Headers>,
42 pub body: Option<Body>,
43}
44
45impl RequestBuilder {
46 pub fn build(self) -> Result<Request, RequestError> {
47 let method = self.method.ok_or(RequestError::MethodIsNone)?;
48 let request_uri = self.request_uri.ok_or(RequestError::RequestUriIsNone)?;
49 let http_version = self.http_version.ok_or(RequestError::HttpVersionIsNone)?;
50 let headers = self.headers.ok_or(RequestError::HeadersIsNone)?;
51 let body = self.body.ok_or(RequestError::BodyIsNone)?;
52 Ok(Request {
53 method,
54 request_uri,
55 http_version,
56 headers,
57 body,
58 })
59 }
60
61 #[inline]
62 pub fn empty() -> RequestBuilder {
63 RequestBuilder {
64 method: None,
65 request_uri: None,
66 http_version: None,
67 headers: None,
68 body: None,
69 }
70 }
71
72 #[inline]
73 pub fn is_empty(&self) -> bool {
74 self.method.is_none()
75 && self.request_uri.is_none()
76 && self.http_version.is_none()
77 && self.headers.is_none()
78 && self.body.is_none()
79 }
80}
81
82impl Add<RequestBuilder> for RequestBuilder {
83 type Output = Self;
84 fn add(mut self, other: Self) -> Self {
85 self.method = self.method.or(other.method);
86 self.request_uri = self.request_uri.or(other.request_uri);
87 self.http_version = self.http_version.or(other.http_version);
88 self.headers = match (self.headers, other.headers) {
89 (a, None) => a,
90 (None, b) => b,
91 (Some(a), Some(b)) => Some(a + b),
92 };
93 self.body = match (self.body, other.body) {
94 (a, None) => a,
95 (None, b) => b,
96 (Some(a), Some(b)) => Some(a + b),
97 };
98 self
99 }
100}
101
102#[derive(Debug, Clone)]
103pub struct Request {
104 method: Method,
105 request_uri: RequestUri,
106 http_version: HttpVersion,
107 headers: Headers,
108 body: Body,
109}
110
111impl From<Request> for Bytes {
112 fn from(x: Request) -> Self {
113 let mut buf = BytesMut::new();
114 buf.put(Bytes::from(x.method));
115 buf.put_u8(sp!());
116 buf.put(Bytes::from(x.request_uri));
117 buf.put_u8(sp!());
118 buf.put(Bytes::from(x.http_version));
119 buf.put_u8(cr!());
120 buf.put_u8(lf!());
121 buf.put(Bytes::from(x.headers));
122 buf.put_u8(cr!());
123 buf.put_u8(lf!());
124 buf.freeze()
125 }
126}