http_protocol/request/
mod.rs

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