Skip to main content

ntex/http/
request.rs

1use std::{cell::Ref, cell::RefMut, fmt, mem, net};
2
3use crate::http::header::{self, HeaderMap};
4use crate::http::httpmessage::HttpMessage;
5use crate::http::message::{Message, RequestHead};
6use crate::http::{Method, Uri, Version, payload::Payload};
7use crate::{io::IoRef, io::types, util::Extensions};
8
9/// Request
10pub struct Request {
11    pub(crate) payload: Payload,
12    pub(crate) head: Message<RequestHead>,
13}
14
15impl HttpMessage for Request {
16    #[inline]
17    fn message_headers(&self) -> &HeaderMap {
18        &self.head().headers
19    }
20
21    /// Request extensions
22    #[inline]
23    fn message_extensions(&self) -> Ref<'_, Extensions> {
24        self.head.extensions()
25    }
26
27    /// Mutable reference to a the request's extensions
28    #[inline]
29    fn message_extensions_mut(&self) -> RefMut<'_, Extensions> {
30        self.head.extensions_mut()
31    }
32}
33
34impl From<Message<RequestHead>> for Request {
35    fn from(head: Message<RequestHead>) -> Self {
36        Request {
37            head,
38            payload: Payload::None,
39        }
40    }
41}
42
43impl Request {
44    /// Create new Request instance
45    pub fn new() -> Request {
46        Request {
47            head: Message::new(),
48            payload: Payload::None,
49        }
50    }
51}
52
53impl Request {
54    /// Create new Request instance
55    pub fn with_payload(payload: Payload) -> Request {
56        Request {
57            payload,
58            head: Message::new(),
59        }
60    }
61
62    #[inline]
63    /// Http message part of the request
64    pub fn head(&self) -> &RequestHead {
65        &self.head
66    }
67
68    #[inline]
69    #[doc(hidden)]
70    /// Mutable reference to a http message part of the request
71    pub fn head_mut(&mut self) -> &mut RequestHead {
72        &mut self.head
73    }
74
75    /// Request's uri.
76    #[inline]
77    pub fn uri(&self) -> &Uri {
78        &self.head().uri
79    }
80
81    /// Mutable reference to the request's uri.
82    #[inline]
83    pub fn uri_mut(&mut self) -> &mut Uri {
84        &mut self.head_mut().uri
85    }
86
87    /// Read the Request method.
88    #[inline]
89    pub fn method(&self) -> &Method {
90        &self.head().method
91    }
92
93    /// Read the Request Version.
94    #[inline]
95    pub fn version(&self) -> Version {
96        self.head().version
97    }
98
99    /// The target path of this Request.
100    #[inline]
101    pub fn path(&self) -> &str {
102        self.head().uri.path()
103    }
104
105    #[inline]
106    /// Request's headers.
107    pub fn headers(&self) -> &HeaderMap {
108        &self.head().headers
109    }
110
111    /// Mutable reference to the message's headers.
112    pub fn headers_mut(&mut self) -> &mut HeaderMap {
113        &mut self.head_mut().headers
114    }
115
116    /// Check if request requires connection upgrade
117    #[inline]
118    pub fn upgrade(&self) -> bool {
119        self.head().upgrade() || self.head().method == Method::CONNECT
120    }
121
122    /// Io reference for current connection
123    #[inline]
124    pub fn io(&self) -> Option<&IoRef> {
125        self.head().io.as_ref()
126    }
127
128    /// Peer socket address
129    ///
130    /// Peer address is actual socket address, if proxy is used in front of
131    /// ntex http server, then peer address would be address of this proxy.
132    #[inline]
133    pub fn peer_addr(&self) -> Option<net::SocketAddr> {
134        self.head().io.as_ref().and_then(|io| {
135            io.query::<types::PeerAddr>()
136                .get()
137                .map(types::PeerAddr::into_inner)
138        })
139    }
140
141    /// Get request's payload
142    pub fn payload(&mut self) -> &mut Payload {
143        &mut self.payload
144    }
145
146    /// Get request's payload
147    pub fn take_payload(&mut self) -> Payload {
148        mem::take(&mut self.payload)
149    }
150
151    /// Replace request's payload, returns old one
152    pub fn replace_payload(&mut self, payload: Payload) -> Payload {
153        mem::replace(&mut self.payload, payload)
154    }
155
156    /// Request extensions
157    #[inline]
158    pub fn extensions(&self) -> Ref<'_, Extensions> {
159        self.head.extensions()
160    }
161
162    /// Mutable reference to a the request's extensions
163    #[inline]
164    pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
165        self.head.extensions_mut()
166    }
167
168    /// Split request into request head and payload
169    pub(crate) fn into_parts(self) -> (Message<RequestHead>, Payload) {
170        (self.head, self.payload)
171    }
172}
173
174impl Default for Request {
175    fn default() -> Request {
176        Request::new()
177    }
178}
179
180impl fmt::Debug for Request {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182        writeln!(
183            f,
184            "\nRequest {:?} {}:{}",
185            self.version(),
186            self.method(),
187            self.path()
188        )?;
189        if let Some(q) = self.uri().query().as_ref() {
190            writeln!(f, "  query: ?{q:?}")?;
191        }
192        writeln!(f, "  headers:")?;
193        for (key, val) in self.headers() {
194            if key == header::AUTHORIZATION {
195                writeln!(f, "    {key:?}: <REDACTED>")?;
196            } else {
197                writeln!(f, "    {key:?}: {val:?}")?;
198            }
199        }
200        Ok(())
201    }
202}
203
204#[cfg(test)]
205mod tests {
206    use super::*;
207
208    #[test]
209    fn test_basics() {
210        let msg = Message::new();
211        let req = Request::new();
212        assert!(req.io().is_none());
213        let mut req = Request::from(msg);
214        assert!(req.io().is_none());
215
216        req.headers_mut().insert(
217            header::CONTENT_TYPE,
218            header::HeaderValue::from_static("text/plain"),
219        );
220        assert!(req.headers().contains_key(header::CONTENT_TYPE));
221
222        req.extensions_mut()
223            .insert(header::HeaderValue::from_static("text/plain"));
224        assert_eq!(
225            req.extensions().get::<header::HeaderValue>().unwrap(),
226            header::HeaderValue::from_static("text/plain")
227        );
228
229        req.head_mut().headers_mut().insert(
230            header::CONTENT_LENGTH,
231            header::HeaderValue::from_static("100"),
232        );
233        assert!(req.headers().contains_key(header::CONTENT_LENGTH));
234
235        req.head_mut().no_chunking(true);
236        assert!(!req.head().chunked());
237        req.head_mut().no_chunking(false);
238        assert!(req.head().chunked());
239
240        *req.uri_mut() = Uri::try_from("/index.html?q=1").unwrap();
241        assert_eq!(req.uri().path(), "/index.html");
242        assert_eq!(req.uri().query(), Some("q=1"));
243
244        let s = format!("{req:?}");
245        assert!(s.contains("Request HTTP/1.1 GET:/index.html"));
246
247        let s = format!("{:?}", req.head());
248        assert!(s.contains("RequestHead { id: 0, uri:"));
249    }
250}