actix_http/requests/
request.rs1use std::{
4 cell::{Ref, RefCell, RefMut},
5 fmt, mem, net,
6 rc::Rc,
7 str,
8};
9
10use http::{header, Method, Uri, Version};
11
12use crate::{
13 header::HeaderMap, BoxedPayloadStream, Extensions, HttpMessage, Message, Payload, RequestHead,
14};
15
16pub struct Request<P = BoxedPayloadStream> {
18 pub(crate) payload: Payload<P>,
19 pub(crate) head: Message<RequestHead>,
20 pub(crate) conn_data: Option<Rc<Extensions>>,
21 pub(crate) extensions: RefCell<Extensions>,
22}
23
24impl<P> HttpMessage for Request<P> {
25 type Stream = P;
26
27 #[inline]
28 fn headers(&self) -> &HeaderMap {
29 &self.head().headers
30 }
31
32 fn take_payload(&mut self) -> Payload<P> {
33 mem::replace(&mut self.payload, Payload::None)
34 }
35
36 #[inline]
37 fn extensions(&self) -> Ref<'_, Extensions> {
38 self.extensions.borrow()
39 }
40
41 #[inline]
42 fn extensions_mut(&self) -> RefMut<'_, Extensions> {
43 self.extensions.borrow_mut()
44 }
45}
46
47impl From<Message<RequestHead>> for Request<BoxedPayloadStream> {
48 fn from(head: Message<RequestHead>) -> Self {
49 Request {
50 head,
51 payload: Payload::None,
52 extensions: RefCell::new(Extensions::default()),
53 conn_data: None,
54 }
55 }
56}
57
58impl Request<BoxedPayloadStream> {
59 #[allow(clippy::new_without_default)]
61 pub fn new() -> Request<BoxedPayloadStream> {
62 Request {
63 head: Message::new(),
64 payload: Payload::None,
65 extensions: RefCell::new(Extensions::default()),
66 conn_data: None,
67 }
68 }
69}
70
71impl<P> Request<P> {
72 pub fn with_payload(payload: Payload<P>) -> Request<P> {
74 Request {
75 payload,
76 head: Message::new(),
77 extensions: RefCell::new(Extensions::default()),
78 conn_data: None,
79 }
80 }
81
82 pub fn replace_payload<P1>(self, payload: Payload<P1>) -> (Request<P1>, Payload<P>) {
84 let pl = self.payload;
85
86 (
87 Request {
88 payload,
89 head: self.head,
90 extensions: self.extensions,
91 conn_data: self.conn_data,
92 },
93 pl,
94 )
95 }
96
97 pub fn payload(&mut self) -> &mut Payload<P> {
99 &mut self.payload
100 }
101
102 pub fn take_payload(&mut self) -> Payload<P> {
104 mem::replace(&mut self.payload, Payload::None)
105 }
106
107 pub fn into_parts(self) -> (Message<RequestHead>, Payload<P>) {
109 (self.head, self.payload)
110 }
111
112 #[inline]
113 pub fn head(&self) -> &RequestHead {
115 &self.head
116 }
117
118 #[inline]
119 #[doc(hidden)]
120 pub fn head_mut(&mut self) -> &mut RequestHead {
122 &mut self.head
123 }
124
125 pub fn headers_mut(&mut self) -> &mut HeaderMap {
127 &mut self.head.headers
128 }
129
130 #[inline]
132 pub fn uri(&self) -> &Uri {
133 &self.head().uri
134 }
135
136 #[inline]
138 pub fn uri_mut(&mut self) -> &mut Uri {
139 &mut self.head.uri
140 }
141
142 #[inline]
144 pub fn method(&self) -> &Method {
145 &self.head().method
146 }
147
148 #[inline]
150 pub fn version(&self) -> Version {
151 self.head().version
152 }
153
154 #[inline]
156 pub fn path(&self) -> &str {
157 self.head().uri.path()
158 }
159
160 #[inline]
162 pub fn upgrade(&self) -> bool {
163 if let Some(conn) = self.head().headers.get(header::CONNECTION) {
164 if let Ok(s) = conn.to_str() {
165 return s.to_lowercase().contains("upgrade");
166 }
167 }
168 self.head().method == Method::CONNECT
169 }
170
171 #[inline]
178 pub fn peer_addr(&self) -> Option<net::SocketAddr> {
179 self.head().peer_addr
180 }
181
182 pub fn conn_data<T: 'static>(&self) -> Option<&T> {
190 self.conn_data
191 .as_deref()
192 .and_then(|container| container.get::<T>())
193 }
194
195 pub fn take_conn_data(&mut self) -> Option<Rc<Extensions>> {
200 self.conn_data.take()
201 }
202
203 pub fn take_req_data(&mut self) -> Extensions {
205 mem::take(self.extensions.get_mut())
206 }
207}
208
209impl<P> fmt::Debug for Request<P> {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 writeln!(
212 f,
213 "\nRequest {:?} {}:{}",
214 self.version(),
215 self.method(),
216 self.path()
217 )?;
218
219 if let Some(q) = self.uri().query().as_ref() {
220 writeln!(f, " query: ?{:?}", q)?;
221 }
222
223 writeln!(f, " headers:")?;
224
225 for (key, val) in self.headers().iter() {
226 writeln!(f, " {:?}: {:?}", key, val)?;
227 }
228
229 Ok(())
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236
237 #[test]
238 fn test_basics() {
239 let msg = Message::new();
240 let mut req = Request::from(msg);
241 req.headers_mut().insert(
242 header::CONTENT_TYPE,
243 header::HeaderValue::from_static("text/plain"),
244 );
245 assert!(req.headers().contains_key(header::CONTENT_TYPE));
246
247 *req.uri_mut() = Uri::try_from("/index.html?q=1").unwrap();
248 assert_eq!(req.uri().path(), "/index.html");
249 assert_eq!(req.uri().query(), Some("q=1"));
250
251 let s = format!("{:?}", req);
252 assert!(s.contains("Request HTTP/1.1 GET:/index.html"));
253 }
254}