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}