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