http_types_rs/
request.rs

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