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}