ttpkit_http/server/
request.rs1use std::{borrow::Borrow, net::SocketAddr, ops::Deref};
4
5use crate::{
6 Body, Error, Scheme,
7 request::{Request, RequestHeader},
8 url::{IntoUrl, QueryDict, Url},
9};
10
11pub struct IncomingRequest<B = Body> {
13 inner: Box<InnerRequest<B>>,
14}
15
16impl<B> IncomingRequest<B> {
17 pub fn new(
19 url_scheme: Scheme,
20 server_addr: SocketAddr,
21 client_addr: SocketAddr,
22 header: RequestHeader,
23 body: B,
24 ) -> Result<Self, Error> {
25 let context = RequestContext::new(url_scheme, server_addr, client_addr, &header)?;
26
27 let inner = InnerRequest {
28 inner: Request::new(header, body),
29 context,
30 };
31
32 let res = Self {
33 inner: Box::new(inner),
34 };
35
36 Ok(res)
37 }
38
39 #[inline]
41 pub fn url(&self) -> &Url {
42 &self.inner.context.url
43 }
44
45 #[inline]
47 pub fn query_parameters(&self) -> &QueryDict {
48 &self.inner.context.query
49 }
50
51 #[inline]
53 pub fn server_addr(&self) -> SocketAddr {
54 self.inner.context.server_addr
55 }
56
57 #[inline]
59 pub fn client_addr(&self) -> SocketAddr {
60 self.inner.context.client_addr
61 }
62
63 #[inline]
65 pub fn body(self) -> B {
66 self.inner.inner.body()
67 }
68
69 #[inline]
71 pub fn deconstruct(self) -> (RequestHeader, B) {
72 self.inner.inner.deconstruct()
73 }
74}
75
76impl<B> AsRef<Request<B>> for IncomingRequest<B> {
77 #[inline]
78 fn as_ref(&self) -> &Request<B> {
79 &self.inner.inner
80 }
81}
82
83impl<B> Borrow<Request<B>> for IncomingRequest<B> {
84 #[inline]
85 fn borrow(&self) -> &Request<B> {
86 &self.inner.inner
87 }
88}
89
90impl<B> Deref for IncomingRequest<B> {
91 type Target = Request<B>;
92
93 #[inline]
94 fn deref(&self) -> &Self::Target {
95 &self.inner.inner
96 }
97}
98
99struct RequestContext {
101 url: Url,
102 query: QueryDict,
103 server_addr: SocketAddr,
104 client_addr: SocketAddr,
105}
106
107impl RequestContext {
108 fn new(
110 url_scheme: Scheme,
111 server_addr: SocketAddr,
112 client_addr: SocketAddr,
113 header: &RequestHeader,
114 ) -> Result<Self, Error> {
115 let host = header
116 .get_header_field_value("host")
117 .map(|h| h.to_str())
118 .and_then(|res| res.ok())
119 .map(|h| {
120 if let Some((host, _)) = h.split_once(':') {
121 host
122 } else {
123 h
124 }
125 })
126 .map(String::from)
127 .unwrap_or_else(|| format!("{}", server_addr.ip()));
128
129 let port = server_addr.port();
130
131 let path = header
132 .path()
133 .to_str()
134 .map_err(|_| Error::from_static_msg("unable to reconstruct request URL"))?;
135
136 let url = if port == url_scheme.default_port() {
137 format!("{url_scheme}://{host}{path}")
138 } else {
139 format!("{url_scheme}://{host}:{port}{path}")
140 };
141
142 let url = url
143 .into_url()
144 .map_err(|_| Error::from_static_msg("unable to reconstruct request URL"))?;
145
146 let query = url
147 .query()
148 .unwrap_or("")
149 .parse()
150 .map_err(|_| Error::from_static_msg("unable to parse request query parameters"))?;
151
152 let res = Self {
153 url,
154 query,
155 server_addr,
156 client_addr,
157 };
158
159 Ok(res)
160 }
161}
162
163struct InnerRequest<B> {
168 inner: Request<B>,
169 context: RequestContext,
170}