http_types/request.rs
1use futures_lite::{io, prelude::*};
2
3use std::convert::{Into, TryInto};
4use std::mem;
5use std::ops::Index;
6use std::pin::Pin;
7use std::task::{Context, Poll};
8
9use crate::convert::{Deserialize, DeserializeOwned, Serialize};
10use crate::headers::{
11 self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values,
12 CONTENT_TYPE,
13};
14use crate::mime::Mime;
15use crate::trailers::{self, Trailers};
16use crate::{Body, Extensions, Method, StatusCode, Url, Version};
17
18pin_project_lite::pin_project! {
19 /// An HTTP request.
20 ///
21 /// # Examples
22 ///
23 /// ```
24 /// use http_types::Request;
25 ///
26 /// let mut req = Request::get("https://example.com");
27 /// req.set_body("Hello, Nori!");
28 /// ```
29 #[derive(Debug)]
30 pub struct Request {
31 method: Method,
32 url: Url,
33 headers: Headers,
34 version: Option<Version>,
35 #[pin]
36 body: Body,
37 local_addr: Option<String>,
38 peer_addr: Option<String>,
39 ext: Extensions,
40 trailers_sender: Option<async_channel::Sender<Trailers>>,
41 trailers_receiver: Option<async_channel::Receiver<Trailers>>,
42 has_trailers: bool,
43 }
44}
45
46impl Request {
47 /// Create a new request.
48 pub fn new<U>(method: Method, url: U) -> Self
49 where
50 U: TryInto<Url>,
51 U::Error: std::fmt::Debug,
52 {
53 let url = url.try_into().expect("Could not convert into a valid url");
54 let (trailers_sender, trailers_receiver) = async_channel::bounded(1);
55 Self {
56 method,
57 url,
58 headers: Headers::new(),
59 version: None,
60 body: Body::empty(),
61 ext: Extensions::new(),
62 peer_addr: None,
63 local_addr: None,
64 trailers_receiver: Some(trailers_receiver),
65 trailers_sender: Some(trailers_sender),
66 has_trailers: false,
67 }
68 }
69
70 /// Sets a string representation of the peer address of this
71 /// request. This might take the form of an ip/fqdn and port or a
72 /// local socket address.
73 pub fn set_peer_addr(&mut self, peer_addr: Option<impl std::string::ToString>) {
74 self.peer_addr = peer_addr.map(|addr| addr.to_string());
75 }
76
77 /// Sets a string representation of the local address that this
78 /// request was received on. This might take the form of an ip/fqdn and
79 /// port, or a local socket address.
80 pub fn set_local_addr(&mut self, local_addr: Option<impl std::string::ToString>) {
81 self.local_addr = local_addr.map(|addr| addr.to_string());
82 }
83
84 /// Get the peer socket address for the underlying transport, if
85 /// that information is available for this request.
86 pub fn peer_addr(&self) -> Option<&str> {
87 self.peer_addr.as_deref()
88 }
89
90 /// Get the local socket address for the underlying transport, if
91 /// that information is available for this request.
92 pub fn local_addr(&self) -> Option<&str> {
93 self.local_addr.as_deref()
94 }
95
96 /// Get the remote address for this request.
97 ///
98 /// This is determined in the following priority:
99 /// 1. `Forwarded` header `for` key
100 /// 2. The first `X-Forwarded-For` header
101 /// 3. Peer address of the transport
102 pub fn remote(&self) -> Option<&str> {
103 self.forwarded_for().or_else(|| self.peer_addr())
104 }
105
106 /// Get the destination host for this request.
107 ///
108 /// This is determined in the following priority:
109 /// 1. `Forwarded` header `host` key
110 /// 2. The first `X-Forwarded-Host` header
111 /// 3. `Host` header
112 /// 4. URL domain, if any
113 pub fn host(&self) -> Option<&str> {
114 self.forwarded_header_part("host")
115 .or_else(|| {
116 self.header("X-Forwarded-Host")
117 .and_then(|h| h.as_str().split(',').next())
118 })
119 .or_else(|| self.header(&headers::HOST).map(|h| h.as_str()))
120 .or_else(|| self.url().host_str())
121 }
122
123 fn forwarded_header_part(&self, part: &str) -> Option<&str> {
124 self.header("Forwarded").and_then(|header| {
125 header.as_str().split(';').find_map(|key_equals_value| {
126 let parts = key_equals_value.split('=').collect::<Vec<_>>();
127 if parts.len() == 2 && parts[0].eq_ignore_ascii_case(part) {
128 Some(parts[1])
129 } else {
130 None
131 }
132 })
133 })
134 }
135
136 fn forwarded_for(&self) -> Option<&str> {
137 self.forwarded_header_part("for").or_else(|| {
138 self.header("X-Forwarded-For")
139 .and_then(|header| header.as_str().split(',').next())
140 })
141 }
142
143 /// Get the HTTP method
144 pub fn method(&self) -> Method {
145 self.method
146 }
147
148 /// Set the HTTP method.
149 pub fn set_method(&mut self, method: Method) {
150 self.method = method;
151 }
152
153 /// Get a reference to the url.
154 ///
155 /// # Examples
156 ///
157 /// ```
158 /// # fn main() -> Result<(), http_types::Error> {
159 /// #
160 /// use http_types::{Request, Response, StatusCode};
161 /// let mut req = Request::get("https://example.com");
162 /// assert_eq!(req.url().scheme(), "https");
163 /// #
164 /// # Ok(()) }
165 /// ```
166 pub fn url(&self) -> &Url {
167 &self.url
168 }
169
170 /// Get a mutable reference to the url.
171 ///
172 /// # Examples
173 ///
174 /// ```
175 /// # fn main() -> Result<(), http_types::Error> {
176 /// #
177 /// use http_types::{Method, Request, Response, StatusCode, Url};
178 /// let mut req = Request::get("https://example.com");
179 /// req.url_mut().set_scheme("http");
180 /// assert_eq!(req.url().scheme(), "http");
181 /// #
182 /// # Ok(()) }
183 /// ```
184 pub fn url_mut(&mut self) -> &mut Url {
185 &mut self.url
186 }
187
188 /// Set the request body.
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// use http_types::{Method, Request};
194 ///
195 /// let mut req = Request::get("https://example.com");
196 /// req.set_body("Hello, Nori!");
197 /// ```
198 pub fn set_body(&mut self, body: impl Into<Body>) {
199 self.replace_body(body);
200 }
201
202 /// Swaps the value of the body with another body, without deinitializing
203 /// either one.
204 ///
205 /// # Examples
206 ///
207 /// ```
208 /// # use async_std::io::prelude::*;
209 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
210 /// #
211 /// use http_types::{Body, Method, Request};
212 ///
213 /// let mut req = Request::get("https://example.com");
214 /// req.set_body("Hello, Nori!");
215 /// let mut body: Body = req.replace_body("Hello, Chashu!");
216 ///
217 /// let mut string = String::new();
218 /// body.read_to_string(&mut string).await?;
219 /// assert_eq!(&string, "Hello, Nori!");
220 /// #
221 /// # Ok(()) }) }
222 /// ```
223 pub fn replace_body(&mut self, body: impl Into<Body>) -> Body {
224 let body = mem::replace(&mut self.body, body.into());
225 self.copy_content_type_from_body();
226 body
227 }
228
229 /// Replace the request body with a new body, and return the old body.
230 ///
231 /// # Examples
232 ///
233 /// ```
234 /// # use async_std::io::prelude::*;
235 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
236 /// #
237 /// use http_types::{Body, Request};
238 ///
239 /// let mut req = Request::get("https://example.com");
240 /// req.set_body("Hello, Nori!");
241 /// let mut body = "Hello, Chashu!".into();
242 /// req.swap_body(&mut body);
243 ///
244 /// let mut string = String::new();
245 /// body.read_to_string(&mut string).await?;
246 /// assert_eq!(&string, "Hello, Nori!");
247 /// #
248 /// # Ok(()) }) }
249 /// ```
250 pub fn swap_body(&mut self, body: &mut Body) {
251 mem::swap(&mut self.body, body);
252 self.copy_content_type_from_body();
253 }
254
255 /// Take the request body, replacing it with an empty body.
256 ///
257 /// # Examples
258 ///
259 /// ```
260 /// # use async_std::io::prelude::*;
261 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
262 /// #
263 /// use http_types::{Body, Request};
264 ///
265 /// let mut req = Request::get("https://example.com");
266 /// req.set_body("Hello, Nori!");
267 /// let mut body: Body = req.take_body();
268 ///
269 /// let mut string = String::new();
270 /// body.read_to_string(&mut string).await?;
271 /// assert_eq!(&string, "Hello, Nori!");
272 ///
273 /// # let mut string = String::new();
274 /// # req.read_to_string(&mut string).await?;
275 /// # assert_eq!(&string, "");
276 /// #
277 /// # Ok(()) }) }
278 /// ```
279 pub fn take_body(&mut self) -> Body {
280 self.replace_body(Body::empty())
281 }
282
283 /// Read the body as a string.
284 ///
285 /// This consumes the request. If you want to read the body without
286 /// consuming the request, consider using the `take_body` method and
287 /// then calling `Body::into_string` or using the Request's AsyncRead
288 /// implementation to read the body.
289 ///
290 /// # Examples
291 ///
292 /// ```
293 /// # use std::io::prelude::*;
294 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
295 /// use async_std::io::Cursor;
296 /// use http_types::{Body, Request};
297 ///
298 /// let mut req = Request::get("https://example.com");
299 ///
300 /// let cursor = Cursor::new("Hello Nori");
301 /// let body = Body::from_reader(cursor, None);
302 /// req.set_body(body);
303 /// assert_eq!(&req.body_string().await.unwrap(), "Hello Nori");
304 /// # Ok(()) }) }
305 /// ```
306 pub async fn body_string(&mut self) -> crate::Result<String> {
307 let body = self.take_body();
308 body.into_string().await
309 }
310
311 /// Read the body as bytes.
312 ///
313 /// This consumes the `Request`. If you want to read the body without
314 /// consuming the request, consider using the `take_body` method and
315 /// then calling `Body::into_bytes` or using the Request's AsyncRead
316 /// implementation to read the body.
317 ///
318 /// # Examples
319 ///
320 /// ```
321 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
322 /// use http_types::{Body, Request};
323 ///
324 /// let bytes = vec![1, 2, 3];
325 /// let mut req = Request::get("https://example.com");
326 /// req.set_body(Body::from_bytes(bytes));
327 ///
328 /// let bytes = req.body_bytes().await?;
329 /// assert_eq!(bytes, vec![1, 2, 3]);
330 /// # Ok(()) }) }
331 /// ```
332 pub async fn body_bytes(&mut self) -> crate::Result<Vec<u8>> {
333 let body = self.take_body();
334 body.into_bytes().await
335 }
336
337 /// Read the body as JSON.
338 ///
339 /// This consumes the request. If you want to read the body without
340 /// consuming the request, consider using the `take_body` method and
341 /// then calling `Body::into_json` or using the Request's AsyncRead
342 /// implementation to read the body.
343 ///
344 /// # Examples
345 ///
346 /// ```
347 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
348 /// use http_types::convert::{Deserialize, Serialize};
349 /// use http_types::{Body, Request};
350 ///
351 /// #[derive(Debug, Serialize, Deserialize)]
352 /// struct Cat {
353 /// name: String,
354 /// }
355 ///
356 /// let cat = Cat {
357 /// name: String::from("chashu"),
358 /// };
359 /// let mut req = Request::get("https://example.com");
360 /// req.set_body(Body::from_json(&cat)?);
361 ///
362 /// let cat: Cat = req.body_json().await?;
363 /// assert_eq!(&cat.name, "chashu");
364 /// # Ok(()) }) }
365 /// ```
366 pub async fn body_json<T: DeserializeOwned>(&mut self) -> crate::Result<T> {
367 let body = self.take_body();
368 body.into_json().await
369 }
370
371 /// Read the body as `x-www-form-urlencoded`.
372 ///
373 /// This consumes the request. If you want to read the body without
374 /// consuming the request, consider using the `take_body` method and
375 /// then calling `Body::into_json` or using the Request's AsyncRead
376 /// implementation to read the body.
377 ///
378 /// # Examples
379 ///
380 /// ```
381 /// # fn main() -> http_types::Result<()> { async_std::task::block_on(async {
382 /// use http_types::convert::{Deserialize, Serialize};
383 /// use http_types::{Body, Request};
384 ///
385 /// #[derive(Debug, Serialize, Deserialize)]
386 /// struct Cat {
387 /// name: String,
388 /// }
389 ///
390 /// let cat = Cat {
391 /// name: String::from("chashu"),
392 /// };
393 /// let mut req = Request::get("https://example.com");
394 /// req.set_body(Body::from_form(&cat)?);
395 ///
396 /// let cat: Cat = req.body_form().await?;
397 /// assert_eq!(&cat.name, "chashu");
398 /// # Ok(()) }) }
399 /// ```
400 pub async fn body_form<T: DeserializeOwned>(&mut self) -> crate::Result<T> {
401 let body = self.take_body();
402 body.into_form().await
403 }
404
405 /// Get an HTTP header.
406 pub fn header(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
407 self.headers.get(name)
408 }
409
410 /// Get a mutable reference to a header.
411 pub fn header_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
412 self.headers.get_mut(name.into())
413 }
414
415 /// Remove a header.
416 pub fn remove_header(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
417 self.headers.remove(name.into())
418 }
419
420 /// Set an HTTP header.
421 ///
422 /// # Examples
423 ///
424 /// ```
425 /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
426 /// #
427 /// use http_types::Request;
428 ///
429 /// let mut req = Request::get("https://example.com");
430 /// req.insert_header("Content-Type", "text/plain");
431 /// #
432 /// # Ok(()) }
433 /// ```
434 pub fn insert_header(
435 &mut self,
436 name: impl Into<HeaderName>,
437 values: impl ToHeaderValues,
438 ) -> Option<HeaderValues> {
439 self.headers.insert(name, values)
440 }
441
442 /// Append a header to the headers.
443 ///
444 /// Unlike `insert` this function will not override the contents of a
445 /// header, but insert a header if there aren't any. Or else append to
446 /// the existing list of headers.
447 ///
448 /// # Examples
449 ///
450 /// ```
451 /// # fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
452 /// #
453 /// use http_types::Request;
454 ///
455 /// let mut req = Request::get("https://example.com");
456 /// req.append_header("Content-Type", "text/plain");
457 /// #
458 /// # Ok(()) }
459 /// ```
460 pub fn append_header(&mut self, name: impl Into<HeaderName>, values: impl ToHeaderValues) {
461 self.headers.append(name, values)
462 }
463
464 /// Set the response MIME.
465 // TODO: return a parsed MIME
466 pub fn set_content_type(&mut self, mime: Mime) -> Option<HeaderValues> {
467 let value: HeaderValue = mime.into();
468
469 // A Mime instance is guaranteed to be valid header name.
470 self.insert_header(CONTENT_TYPE, value)
471 }
472
473 /// Copy MIME data from the body.
474 fn copy_content_type_from_body(&mut self) {
475 if self.header(CONTENT_TYPE).is_none() {
476 self.set_content_type(self.body.mime().clone());
477 }
478 }
479
480 /// Get the current content type
481 pub fn content_type(&self) -> Option<Mime> {
482 self.header(CONTENT_TYPE)?.last().as_str().parse().ok()
483 }
484
485 /// Get the length of the body stream, if it has been set.
486 ///
487 /// This value is set when passing a fixed-size object into as the body.
488 /// E.g. a string, or a buffer. Consumers of this API should check this
489 /// value to decide whether to use `Chunked` encoding, or set the
490 /// response length.
491 pub fn len(&self) -> Option<usize> {
492 self.body.len()
493 }
494
495 /// Returns `true` if the request has a set body stream length of zero,
496 /// `false` otherwise.
497 pub fn is_empty(&self) -> Option<bool> {
498 self.body.is_empty()
499 }
500
501 /// Get the HTTP version, if one has been set.
502 ///
503 /// # Examples
504 ///
505 /// ```
506 /// use http_types::{Request, Version};
507 ///
508 /// # fn main() -> Result<(), http_types::Error> {
509 /// #
510 /// let mut req = Request::get("https://example.com");
511 /// assert_eq!(req.version(), None);
512 ///
513 /// req.set_version(Some(Version::Http2_0));
514 /// assert_eq!(req.version(), Some(Version::Http2_0));
515 /// #
516 /// # Ok(()) }
517 /// ```
518 pub fn version(&self) -> Option<Version> {
519 self.version
520 }
521
522 /// Set the HTTP version.
523 ///
524 /// # Examples
525 ///
526 /// ```
527 /// use http_types::{Request, Version};
528 ///
529 /// # fn main() -> Result<(), http_types::Error> {
530 /// #
531 /// let mut req = Request::get("https://example.com");
532 /// req.set_version(Some(Version::Http2_0));
533 /// #
534 /// # Ok(()) }
535 /// ```
536 pub fn set_version(&mut self, version: Option<Version>) {
537 self.version = version;
538 }
539
540 /// Sends trailers to the a receiver.
541 pub fn send_trailers(&mut self) -> trailers::Sender {
542 self.has_trailers = true;
543 let sender = self
544 .trailers_sender
545 .take()
546 .expect("Trailers sender can only be constructed once");
547 trailers::Sender::new(sender)
548 }
549
550 /// Receive trailers from a sender.
551 pub fn recv_trailers(&mut self) -> trailers::Receiver {
552 let receiver = self
553 .trailers_receiver
554 .take()
555 .expect("Trailers receiver can only be constructed once");
556 trailers::Receiver::new(receiver)
557 }
558
559 /// Returns `true` if sending trailers is in progress.
560 pub fn has_trailers(&self) -> bool {
561 self.has_trailers
562 }
563
564 /// An iterator visiting all header pairs in arbitrary order.
565 pub fn iter(&self) -> headers::Iter<'_> {
566 self.headers.iter()
567 }
568
569 /// An iterator visiting all header pairs in arbitrary order, with mutable
570 /// references to the values.
571 pub fn iter_mut(&mut self) -> headers::IterMut<'_> {
572 self.headers.iter_mut()
573 }
574
575 /// An iterator visiting all header names in arbitrary order.
576 pub fn header_names(&self) -> Names<'_> {
577 self.headers.names()
578 }
579
580 /// An iterator visiting all header values in arbitrary order.
581 pub fn header_values(&self) -> Values<'_> {
582 self.headers.values()
583 }
584
585 /// Returns a reference to the existing local state.
586 pub fn ext(&self) -> &Extensions {
587 &self.ext
588 }
589
590 /// Returns a mutuable reference to the existing local state.
591 ///
592 /// # Examples
593 ///
594 /// ```
595 /// # fn main() -> Result<(), http_types::Error> {
596 /// #
597 /// use http_types::{Request, Version};
598 ///
599 /// let mut req = Request::get("https://example.com");
600 /// req.ext_mut().insert("hello from the extension");
601 /// assert_eq!(req.ext().get(), Some(&"hello from the extension"));
602 /// #
603 /// # Ok(()) }
604 /// ```
605 pub fn ext_mut(&mut self) -> &mut Extensions {
606 &mut self.ext
607 }
608
609 /// Get the URL querystring.
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// use http_types::convert::Deserialize;
615 /// use http_types::Request;
616 /// use std::collections::HashMap;
617 ///
618 /// // An owned structure:
619 ///
620 /// #[derive(Deserialize)]
621 /// struct Index {
622 /// page: u32,
623 /// selections: HashMap<String, String>,
624 /// }
625 ///
626 /// let mut req = Request::get("https://httpbin.org/get?page=2&selections[width]=narrow&selections[height]=tall");
627 /// let Index { page, selections } = req.query().unwrap();
628 /// assert_eq!(page, 2);
629 /// assert_eq!(selections["width"], "narrow");
630 /// assert_eq!(selections["height"], "tall");
631 ///
632 /// // Using borrows:
633 ///
634 /// #[derive(Deserialize)]
635 /// struct Query<'q> {
636 /// format: &'q str,
637 /// }
638 ///
639 /// let mut req = Request::get("https://httpbin.org/get?format=bananna");
640 /// let Query { format } = req.query().unwrap();
641 /// assert_eq!(format, "bananna");
642 /// ```
643 pub fn query<'de, T: Deserialize<'de>>(&'de self) -> crate::Result<T> {
644 // Default to an empty query string if no query parameter has been specified.
645 // This allows successful deserialisation of structs where all fields are optional
646 // when none of those fields has actually been passed by the caller.
647 let query = self.url().query().unwrap_or("");
648 serde_qs::from_str(query).map_err(|e| {
649 // Return the displayable version of the deserialisation error to the caller
650 // for easier debugging.
651 crate::Error::from_str(StatusCode::BadRequest, format!("{}", e))
652 })
653 }
654
655 /// Set the URL querystring.
656 ///
657 /// # Examples
658 ///
659 /// ```
660 /// use http_types::convert::Serialize;
661 /// use http_types::{Method, Request};
662 /// use std::collections::HashMap;
663 ///
664 /// #[derive(Serialize)]
665 /// struct Index {
666 /// page: u32,
667 /// topics: Vec<&'static str>,
668 /// }
669 ///
670 /// let query = Index { page: 2, topics: vec!["rust", "crabs", "crustaceans"] };
671 /// let mut req = Request::get("https://httpbin.org/get");
672 /// req.set_query(&query).unwrap();
673 /// assert_eq!(req.url().query(), Some("page=2&topics[0]=rust&topics[1]=crabs&topics[2]=crustaceans"));
674 /// ```
675 pub fn set_query(&mut self, query: &impl Serialize) -> crate::Result<()> {
676 let query = serde_qs::to_string(query)
677 .map_err(|e| crate::Error::from_str(StatusCode::BadRequest, format!("{}", e)))?;
678 self.url.set_query(Some(&query));
679 Ok(())
680 }
681
682 /// Create a `GET` request.
683 ///
684 /// The `GET` method requests a representation of the specified resource.
685 /// Requests using `GET` should only retrieve data.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// use http_types::{Method, Request};
691 ///
692 /// let mut req = Request::get("https://example.com");
693 /// req.set_body("Hello, Nori!");
694 /// assert_eq!(req.method(), Method::Get);
695 /// ```
696 pub fn get<U>(url: U) -> Self
697 where
698 U: TryInto<Url>,
699 U::Error: std::fmt::Debug,
700 {
701 Request::new(Method::Get, url)
702 }
703
704 /// Create a `HEAD` request.
705 ///
706 /// The `HEAD` method asks for a response identical to that of a `GET`
707 /// request, but without the response body.
708 ///
709 /// # Examples
710 ///
711 /// ```
712 /// use http_types::{Method, Request};
713 ///
714 /// let mut req = Request::head("https://example.com");
715 /// assert_eq!(req.method(), Method::Head);
716 /// ```
717 pub fn head<U>(url: U) -> Self
718 where
719 U: TryInto<Url>,
720 U::Error: std::fmt::Debug,
721 {
722 Request::new(Method::Head, url)
723 }
724
725 /// Create a `POST` request.
726 ///
727 /// The `POST` method is used to submit an entity to the specified resource,
728 /// often causing a change in state or side effects on the server.
729 ///
730 /// # Examples
731 ///
732 /// ```
733 /// use http_types::{Method, Request};
734 ///
735 /// let mut req = Request::post("https://example.com");
736 /// assert_eq!(req.method(), Method::Post);
737 /// ```
738 pub fn post<U>(url: U) -> Self
739 where
740 U: TryInto<Url>,
741 U::Error: std::fmt::Debug,
742 {
743 Request::new(Method::Post, url)
744 }
745
746 /// Create a `PUT` request.
747 ///
748 /// The `PUT` method replaces all current representations of the target
749 /// resource with the request payload.
750 ///
751 /// # Examples
752 ///
753 /// ```
754 /// use http_types::{Method, Request};
755 ///
756 /// let mut req = Request::put("https://example.com");
757 /// assert_eq!(req.method(), Method::Put);
758 /// ```
759 pub fn put<U>(url: U) -> Self
760 where
761 U: TryInto<Url>,
762 U::Error: std::fmt::Debug,
763 {
764 Request::new(Method::Put, url)
765 }
766
767 /// Create a `DELETE` request.
768 ///
769 /// The `DELETE` method deletes the specified resource.
770 ///
771 /// # Examples
772 ///
773 /// ```
774 /// use http_types::{Method, Request};
775 ///
776 /// let mut req = Request::delete("https://example.com");
777 /// assert_eq!(req.method(), Method::Delete);
778 /// ```
779 pub fn delete<U>(url: U) -> Self
780 where
781 U: TryInto<Url>,
782 U::Error: std::fmt::Debug,
783 {
784 Request::new(Method::Delete, url)
785 }
786
787 /// Create a `CONNECT` request.
788 ///
789 /// The `CONNECT` method establishes a tunnel to the server identified by
790 /// the target resource.
791 ///
792 /// # Examples
793 ///
794 /// ```
795 /// use http_types::{Method, Request};
796 ///
797 /// let mut req = Request::connect("https://example.com");
798 /// assert_eq!(req.method(), Method::Connect);
799 /// ```
800 pub fn connect<U>(url: U) -> Self
801 where
802 U: TryInto<Url>,
803 U::Error: std::fmt::Debug,
804 {
805 Request::new(Method::Connect, url)
806 }
807
808 /// Create a `OPTIONS` request.
809 ///
810 /// The `OPTIONS` method is used to describe the communication options for
811 /// the target resource.
812 ///
813 /// # Examples
814 ///
815 /// ```
816 /// use http_types::{Method, Request};
817 ///
818 /// let mut req = Request::options("https://example.com");
819 /// assert_eq!(req.method(), Method::Options);
820 /// ```
821 pub fn options<U>(url: U) -> Self
822 where
823 U: TryInto<Url>,
824 U::Error: std::fmt::Debug,
825 {
826 Request::new(Method::Options, url)
827 }
828
829 /// Create a `TRACE` request.
830 ///
831 /// The `TRACE` method performs a message loop-back test along the path to
832 /// the target resource.
833 ///
834 /// # Examples
835 ///
836 /// ```
837 /// use http_types::{Method, Request};
838 ///
839 /// let mut req = Request::trace("https://example.com");
840 /// assert_eq!(req.method(), Method::Trace);
841 /// ```
842 pub fn trace<U>(url: U) -> Self
843 where
844 U: TryInto<Url>,
845 U::Error: std::fmt::Debug,
846 {
847 Request::new(Method::Trace, url)
848 }
849
850 /// Create a `PATCH` request.
851 ///
852 /// The `PATCH` method is used to apply partial modifications to a resource.
853 ///
854 /// # Examples
855 ///
856 /// ```
857 /// use http_types::{Method, Request};
858 ///
859 /// let mut req = Request::patch("https://example.com");
860 /// assert_eq!(req.method(), Method::Patch);
861 /// ```
862 pub fn patch<U>(url: U) -> Self
863 where
864 U: TryInto<Url>,
865 U::Error: std::fmt::Debug,
866 {
867 Request::new(Method::Patch, url)
868 }
869}
870
871impl Clone for Request {
872 /// Clone the request, resolving the body to `Body::empty()` and removing
873 /// extensions.
874 fn clone(&self) -> Self {
875 Request {
876 method: self.method,
877 url: self.url.clone(),
878 headers: self.headers.clone(),
879 version: self.version,
880 trailers_sender: None,
881 trailers_receiver: None,
882 body: Body::empty(),
883 ext: Extensions::new(),
884 peer_addr: self.peer_addr.clone(),
885 local_addr: self.local_addr.clone(),
886 has_trailers: false,
887 }
888 }
889}
890
891impl AsyncRead for Request {
892 #[allow(missing_doc_code_examples)]
893 fn poll_read(
894 mut self: Pin<&mut Self>,
895 cx: &mut Context<'_>,
896 buf: &mut [u8],
897 ) -> Poll<io::Result<usize>> {
898 Pin::new(&mut self.body).poll_read(cx, buf)
899 }
900}
901
902impl AsyncBufRead for Request {
903 #[allow(missing_doc_code_examples)]
904 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&'_ [u8]>> {
905 let this = self.project();
906 this.body.poll_fill_buf(cx)
907 }
908
909 fn consume(mut self: Pin<&mut Self>, amt: usize) {
910 Pin::new(&mut self.body).consume(amt)
911 }
912}
913
914impl AsRef<Headers> for Request {
915 fn as_ref(&self) -> &Headers {
916 &self.headers
917 }
918}
919
920impl AsMut<Headers> for Request {
921 fn as_mut(&mut self) -> &mut Headers {
922 &mut self.headers
923 }
924}
925
926impl From<Request> for Body {
927 fn from(req: Request) -> Body {
928 req.body
929 }
930}
931
932impl Index<HeaderName> for Request {
933 type Output = HeaderValues;
934
935 /// Returns a reference to the value corresponding to the supplied name.
936 ///
937 /// # Panics
938 ///
939 /// Panics if the name is not present in `Request`.
940 #[inline]
941 fn index(&self, name: HeaderName) -> &HeaderValues {
942 self.headers.index(name)
943 }
944}
945
946impl Index<&str> for Request {
947 type Output = HeaderValues;
948
949 /// Returns a reference to the value corresponding to the supplied name.
950 ///
951 /// # Panics
952 ///
953 /// Panics if the name is not present in `Request`.
954 #[inline]
955 fn index(&self, name: &str) -> &HeaderValues {
956 self.headers.index(name)
957 }
958}
959
960impl IntoIterator for Request {
961 type Item = (HeaderName, HeaderValues);
962 type IntoIter = headers::IntoIter;
963
964 /// Returns a iterator of references over the remaining items.
965 #[inline]
966 fn into_iter(self) -> Self::IntoIter {
967 self.headers.into_iter()
968 }
969}
970
971impl<'a> IntoIterator for &'a Request {
972 type Item = (&'a HeaderName, &'a HeaderValues);
973 type IntoIter = headers::Iter<'a>;
974
975 #[inline]
976 fn into_iter(self) -> Self::IntoIter {
977 self.headers.iter()
978 }
979}
980
981impl<'a> IntoIterator for &'a mut Request {
982 type Item = (&'a HeaderName, &'a mut HeaderValues);
983 type IntoIter = headers::IterMut<'a>;
984
985 #[inline]
986 fn into_iter(self) -> Self::IntoIter {
987 self.headers.iter_mut()
988 }
989}
990
991#[cfg(test)]
992mod tests {
993 use super::*;
994 mod host {
995 use super::*;
996
997 #[test]
998 fn when_forwarded_header_is_set() {
999 let mut request = build_test_request();
1000 set_forwarded(&mut request, "-");
1001 set_x_forwarded_host(&mut request, "this will not be used");
1002 assert_eq!(request.forwarded_header_part("host"), Some("host.com"));
1003 assert_eq!(request.host(), Some("host.com"));
1004 }
1005
1006 #[test]
1007 fn when_several_x_forwarded_hosts_exist() {
1008 let mut request = build_test_request();
1009 set_x_forwarded_host(&mut request, "expected.host");
1010
1011 assert_eq!(request.forwarded_header_part("host"), None);
1012 assert_eq!(request.host(), Some("expected.host"));
1013 }
1014
1015 #[test]
1016 fn when_only_one_x_forwarded_hosts_exist() {
1017 let mut request = build_test_request();
1018 request.insert_header("x-forwarded-host", "expected.host");
1019 assert_eq!(request.host(), Some("expected.host"));
1020 }
1021
1022 #[test]
1023 fn when_host_header_is_set() {
1024 let mut request = build_test_request();
1025 request.insert_header("host", "host.header");
1026 assert_eq!(request.host(), Some("host.header"));
1027 }
1028
1029 #[test]
1030 fn when_there_are_no_headers() {
1031 let request = build_test_request();
1032 assert_eq!(request.host(), Some("async.rs"));
1033 }
1034
1035 #[test]
1036 fn when_url_has_no_domain() {
1037 let mut request = build_test_request();
1038 *request.url_mut() = Url::parse("x:").unwrap();
1039 assert_eq!(request.host(), None);
1040 }
1041
1042 #[test]
1043 fn when_using_shorthand_with_valid_url_to_create_request_get() {
1044 let url = Url::parse("https://example.com").unwrap();
1045 let req = Request::get(url);
1046 assert_eq!(req.method(), Method::Get);
1047 }
1048
1049 #[test]
1050 fn when_using_shorthand_with_valid_url_to_create_request_head() {
1051 let url = Url::parse("https://example.com").unwrap();
1052 let req = Request::head(url);
1053 assert_eq!(req.method(), Method::Head);
1054 }
1055
1056 #[test]
1057 fn when_using_shorthand_with_valid_url_to_create_request_post() {
1058 let url = Url::parse("https://example.com").unwrap();
1059 let req = Request::post(url);
1060 assert_eq!(req.method(), Method::Post);
1061 }
1062
1063 #[test]
1064 fn when_using_shorthand_with_valid_url_to_create_request_put() {
1065 let url = Url::parse("https://example.com").unwrap();
1066 let req = Request::put(url);
1067 assert_eq!(req.method(), Method::Put);
1068 }
1069
1070 #[test]
1071 fn when_using_shorthand_with_valid_url_to_create_request_delete() {
1072 let url = Url::parse("https://example.com").unwrap();
1073 let req = Request::delete(url);
1074 assert_eq!(req.method(), Method::Delete);
1075 }
1076
1077 #[test]
1078 fn when_using_shorthand_with_valid_url_to_create_request_connect() {
1079 let url = Url::parse("https://example.com").unwrap();
1080 let req = Request::connect(url);
1081 assert_eq!(req.method(), Method::Connect);
1082 }
1083
1084 #[test]
1085 fn when_using_shorthand_with_valid_url_to_create_request_options() {
1086 let url = Url::parse("https://example.com").unwrap();
1087 let req = Request::options(url);
1088 assert_eq!(req.method(), Method::Options);
1089 }
1090
1091 #[test]
1092 fn when_using_shorthand_with_valid_url_to_create_request_trace() {
1093 let url = Url::parse("https://example.com").unwrap();
1094 let req = Request::trace(url);
1095 assert_eq!(req.method(), Method::Trace);
1096 }
1097
1098 #[test]
1099 fn when_using_shorthand_with_valid_url_to_create_request_patch() {
1100 let url = Url::parse("https://example.com").unwrap();
1101 let req = Request::patch(url);
1102 assert_eq!(req.method(), Method::Patch);
1103 }
1104 }
1105
1106 mod remote {
1107 use super::*;
1108 #[test]
1109 fn when_forwarded_is_properly_formatted() {
1110 let mut request = build_test_request();
1111 request.set_peer_addr(Some("127.0.0.1:8000"));
1112 set_forwarded(&mut request, "127.0.0.1:8001");
1113
1114 assert_eq!(request.forwarded_for(), Some("127.0.0.1:8001"));
1115 assert_eq!(request.remote(), Some("127.0.0.1:8001"));
1116 }
1117
1118 #[test]
1119 fn when_forwarded_is_improperly_formatted() {
1120 let mut request = build_test_request();
1121 request.set_peer_addr(Some(
1122 "127.0.0.1:8000".parse::<std::net::SocketAddr>().unwrap(),
1123 ));
1124
1125 request.insert_header("Forwarded", "this is an improperly ;;; formatted header");
1126
1127 assert_eq!(request.forwarded_for(), None);
1128 assert_eq!(request.remote(), Some("127.0.0.1:8000"));
1129 }
1130
1131 #[test]
1132 fn when_x_forwarded_for_is_set() {
1133 let mut request = build_test_request();
1134 request.set_peer_addr(Some(
1135 std::path::PathBuf::from("/dev/random").to_str().unwrap(),
1136 ));
1137 set_x_forwarded_for(&mut request, "forwarded-host.com");
1138
1139 assert_eq!(request.forwarded_for(), Some("forwarded-host.com"));
1140 assert_eq!(request.remote(), Some("forwarded-host.com"));
1141 }
1142
1143 #[test]
1144 fn when_both_forwarding_headers_are_set() {
1145 let mut request = build_test_request();
1146 set_forwarded(&mut request, "forwarded.com");
1147 set_x_forwarded_for(&mut request, "forwarded-for-client.com");
1148 request.peer_addr = Some("127.0.0.1:8000".into());
1149
1150 assert_eq!(request.forwarded_for(), Some("forwarded.com"));
1151 assert_eq!(request.remote(), Some("forwarded.com"));
1152 }
1153
1154 #[test]
1155 fn falling_back_to_peer_addr() {
1156 let mut request = build_test_request();
1157 request.peer_addr = Some("127.0.0.1:8000".into());
1158
1159 assert_eq!(request.forwarded_for(), None);
1160 assert_eq!(request.remote(), Some("127.0.0.1:8000"));
1161 }
1162
1163 #[test]
1164 fn when_no_remote_available() {
1165 let request = build_test_request();
1166 assert_eq!(request.forwarded_for(), None);
1167 assert_eq!(request.remote(), None);
1168 }
1169 }
1170
1171 fn build_test_request() -> Request {
1172 let url = Url::parse("http://async.rs/").unwrap();
1173 Request::new(Method::Get, url)
1174 }
1175
1176 fn set_x_forwarded_for(request: &mut Request, client: &'static str) {
1177 request.insert_header(
1178 "x-forwarded-for",
1179 format!("{},proxy.com,other-proxy.com", client),
1180 );
1181 }
1182
1183 fn set_x_forwarded_host(request: &mut Request, host: &'static str) {
1184 request.insert_header(
1185 "x-forwarded-host",
1186 format!("{},proxy.com,other-proxy.com", host),
1187 );
1188 }
1189
1190 fn set_forwarded(request: &mut Request, client: &'static str) {
1191 request.insert_header(
1192 "Forwarded",
1193 format!("by=something.com;for={};host=host.com;proto=http", client),
1194 );
1195 }
1196}