rama_http_types/request.rs
1use std::fmt;
2
3use crate::Result;
4use crate::{HeaderMap, HeaderName, HeaderValue, Method, Uri, Version, body::Body};
5use rama_core::extensions::{Extension, Extensions, ExtensionsRef};
6use rama_net::ClientIp;
7use rama_utils::macros::generate_set_and_with;
8
9/// Represents an HTTP request.
10///
11/// An HTTP request consists of a head and a potentially optional body. The body
12/// component is generic, enabling arbitrary types to represent the HTTP body.
13/// For example, the body could be `Vec<u8>`, a `Stream` of byte chunks, or a
14/// value that has been deserialized.
15///
16/// # Examples
17///
18/// Creating a `Request` to send
19///
20/// ```no_run
21/// use rama_http_types::{Request, Response};
22///
23/// let mut request = Request::builder()
24/// .uri("https://www.rust-lang.org/")
25/// .header("User-Agent", "my-awesome-agent/1.0");
26///
27/// if needs_awesome_header() {
28/// request = request.header("Awesome", "yes");
29/// }
30///
31/// let response = send(request.body(()).unwrap());
32///
33/// # fn needs_awesome_header() -> bool {
34/// # true
35/// # }
36/// #
37/// fn send(req: Request<()>) -> Response<()> {
38/// // ...
39/// # panic!()
40/// }
41/// ```
42///
43/// Inspecting a request to see what was sent.
44///
45/// ```
46/// use rama_http_types::{Request, Response, Result, StatusCode};
47///
48/// fn respond_to(req: Request<()>) -> Result<Response<()>> {
49/// if req.uri().as_str() != "/awesome-url" {
50/// return Response::builder()
51/// .status(StatusCode::NOT_FOUND)
52/// .body(())
53/// }
54///
55/// let has_awesome_header = req.headers().contains_key("Awesome");
56/// let body = req.body();
57///
58/// // ...
59/// # panic!()
60/// }
61/// ```
62///
63/// Deserialize a request of bytes via json:
64///
65/// ```
66/// use rama_http_types::Request;
67/// use serde::de;
68///
69/// fn deserialize<T>(req: Request<Vec<u8>>) -> serde_json::Result<Request<T>>
70/// where for<'de> T: de::Deserialize<'de>,
71/// {
72/// let (parts, body) = req.into_parts();
73/// let body = serde_json::from_slice(&body)?;
74/// Ok(Request::from_parts(parts, body))
75/// }
76/// #
77/// # fn main() {}
78/// ```
79///
80/// Or alternatively, serialize the body of a request to json
81///
82/// ```
83/// use rama_http_types::Request;
84/// use serde::ser;
85///
86/// fn serialize<T>(req: Request<T>) -> serde_json::Result<Request<Vec<u8>>>
87/// where T: ser::Serialize,
88/// {
89/// let (parts, body) = req.into_parts();
90/// let body = serde_json::to_vec(&body)?;
91/// Ok(Request::from_parts(parts, body))
92/// }
93/// #
94/// # fn main() {}
95/// ```
96#[derive(Clone)]
97pub struct Request<T = Body> {
98 head: Parts,
99 body: T,
100}
101
102#[non_exhaustive]
103#[derive(Clone)]
104pub struct Parts {
105 /// The request's method
106 pub method: Method,
107
108 /// The request's URI
109 pub uri: Uri,
110
111 /// The request's version
112 pub version: Version,
113
114 /// The request's headers
115 pub headers: HeaderMap<HeaderValue>,
116
117 /// The request's extensions
118 pub extensions: Extensions,
119}
120
121impl ExtensionsRef for Parts {
122 fn extensions(&self) -> &Extensions {
123 &self.extensions
124 }
125}
126
127impl ClientIp for Parts {
128 fn client_ip(&self) -> Option<std::net::IpAddr> {
129 rama_net::client_ip::client_ip(self)
130 }
131}
132
133/// An HTTP request builder
134///
135/// This type can be used to construct an instance of `Request`
136/// through a builder-like pattern.
137#[derive(Debug)]
138#[must_use]
139pub struct Builder {
140 inner: Result<Parts>,
141}
142
143impl Request<()> {
144 /// Creates a new builder-style object to manufacture a `Request`
145 ///
146 /// This method returns an instance of `Builder` which can be used to
147 /// create a `Request`.
148 ///
149 /// # Examples
150 ///
151 /// ```
152 /// # use rama_http_types::*;
153 /// let request = Request::builder()
154 /// .method("GET")
155 /// .uri("https://www.rust-lang.org/")
156 /// .header("X-Custom-Foo", "Bar")
157 /// .body(())
158 /// .unwrap();
159 /// ```
160 #[inline]
161 pub fn builder() -> Builder {
162 Builder::new()
163 }
164
165 #[inline]
166 /// Same as [`Request::builder`] but with the given [`Extensions`] to start from.
167 pub fn builder_with_extensions(ext: Extensions) -> Builder {
168 Builder::new_with_extensions(ext)
169 }
170
171 /// Creates a new `Builder` initialized with a GET method and the given URI.
172 ///
173 /// This method returns an instance of `Builder` which can be used to
174 /// create a `Request`.
175 ///
176 /// # Example
177 ///
178 /// ```
179 /// # use rama_http_types::*;
180 ///
181 /// let request = Request::get("https://www.rust-lang.org/")
182 /// .body(())
183 /// .unwrap();
184 /// ```
185 pub fn get<T>(uri: T) -> Builder
186 where
187 T: TryInto<Uri>,
188 <T as TryInto<Uri>>::Error: Into<crate::Error>,
189 {
190 Builder::new().method(Method::GET).uri(uri)
191 }
192
193 /// Creates a new `Builder` initialized with a PUT method and the given URI.
194 ///
195 /// This method returns an instance of `Builder` which can be used to
196 /// create a `Request`.
197 ///
198 /// # Example
199 ///
200 /// ```
201 /// # use rama_http_types::*;
202 ///
203 /// let request = Request::put("https://www.rust-lang.org/")
204 /// .body(())
205 /// .unwrap();
206 /// ```
207 pub fn put<T>(uri: T) -> Builder
208 where
209 T: TryInto<Uri>,
210 <T as TryInto<Uri>>::Error: Into<crate::Error>,
211 {
212 Builder::new().method(Method::PUT).uri(uri)
213 }
214
215 /// Creates a new `Builder` initialized with a POST method and the given URI.
216 ///
217 /// This method returns an instance of `Builder` which can be used to
218 /// create a `Request`.
219 ///
220 /// # Example
221 ///
222 /// ```
223 /// # use rama_http_types::*;
224 ///
225 /// let request = Request::post("https://www.rust-lang.org/")
226 /// .body(())
227 /// .unwrap();
228 /// ```
229 pub fn post<T>(uri: T) -> Builder
230 where
231 T: TryInto<Uri>,
232 <T as TryInto<Uri>>::Error: Into<crate::Error>,
233 {
234 Builder::new().method(Method::POST).uri(uri)
235 }
236
237 /// Creates a new `Builder` initialized with a DELETE method and the given URI.
238 ///
239 /// This method returns an instance of `Builder` which can be used to
240 /// create a `Request`.
241 ///
242 /// # Example
243 ///
244 /// ```
245 /// # use rama_http_types::*;
246 ///
247 /// let request = Request::delete("https://www.rust-lang.org/")
248 /// .body(())
249 /// .unwrap();
250 /// ```
251 pub fn delete<T>(uri: T) -> Builder
252 where
253 T: TryInto<Uri>,
254 <T as TryInto<Uri>>::Error: Into<crate::Error>,
255 {
256 Builder::new().method(Method::DELETE).uri(uri)
257 }
258
259 /// Creates a new `Builder` initialized with an OPTIONS method and the given URI.
260 ///
261 /// This method returns an instance of `Builder` which can be used to
262 /// create a `Request`.
263 ///
264 /// # Example
265 ///
266 /// ```
267 /// # use rama_http_types::*;
268 ///
269 /// let request = Request::options("https://www.rust-lang.org/")
270 /// .body(())
271 /// .unwrap();
272 /// # assert_eq!(*request.method(), Method::OPTIONS);
273 /// ```
274 pub fn options<T>(uri: T) -> Builder
275 where
276 T: TryInto<Uri>,
277 <T as TryInto<Uri>>::Error: Into<crate::Error>,
278 {
279 Builder::new().method(Method::OPTIONS).uri(uri)
280 }
281
282 /// Creates a new `Builder` initialized with a HEAD method and the given URI.
283 ///
284 /// This method returns an instance of `Builder` which can be used to
285 /// create a `Request`.
286 ///
287 /// # Example
288 ///
289 /// ```
290 /// # use rama_http_types::*;
291 ///
292 /// let request = Request::head("https://www.rust-lang.org/")
293 /// .body(())
294 /// .unwrap();
295 /// ```
296 pub fn head<T>(uri: T) -> Builder
297 where
298 T: TryInto<Uri>,
299 <T as TryInto<Uri>>::Error: Into<crate::Error>,
300 {
301 Builder::new().method(Method::HEAD).uri(uri)
302 }
303
304 /// Creates a new `Builder` initialized with a CONNECT method and the given URI.
305 ///
306 /// This method returns an instance of `Builder` which can be used to
307 /// create a `Request`.
308 ///
309 /// # Example
310 ///
311 /// ```
312 /// # use rama_http_types::*;
313 ///
314 /// let request = Request::connect("https://www.rust-lang.org/")
315 /// .body(())
316 /// .unwrap();
317 /// ```
318 pub fn connect<T>(uri: T) -> Builder
319 where
320 T: TryInto<Uri>,
321 <T as TryInto<Uri>>::Error: Into<crate::Error>,
322 {
323 Builder::new().method(Method::CONNECT).uri(uri)
324 }
325
326 /// Creates a new `Builder` initialized with a PATCH method and the given URI.
327 ///
328 /// This method returns an instance of `Builder` which can be used to
329 /// create a `Request`.
330 ///
331 /// # Example
332 ///
333 /// ```
334 /// # use rama_http_types::*;
335 ///
336 /// let request = Request::patch("https://www.rust-lang.org/")
337 /// .body(())
338 /// .unwrap();
339 /// ```
340 pub fn patch<T>(uri: T) -> Builder
341 where
342 T: TryInto<Uri>,
343 <T as TryInto<Uri>>::Error: Into<crate::Error>,
344 {
345 Builder::new().method(Method::PATCH).uri(uri)
346 }
347
348 /// Creates a new `Builder` initialized with a TRACE method and the given URI.
349 ///
350 /// This method returns an instance of `Builder` which can be used to
351 /// create a `Request`.
352 ///
353 /// # Example
354 ///
355 /// ```
356 /// # use rama_http_types::*;
357 ///
358 /// let request = Request::trace("https://www.rust-lang.org/")
359 /// .body(())
360 /// .unwrap();
361 /// ```
362 pub fn trace<T>(uri: T) -> Builder
363 where
364 T: TryInto<Uri>,
365 <T as TryInto<Uri>>::Error: Into<crate::Error>,
366 {
367 Builder::new().method(Method::TRACE).uri(uri)
368 }
369
370 /// Creates a new `Builder` initialized with a QUERY method and the given URI.
371 ///
372 /// QUERY ([RFC 10008](https://www.rfc-editor.org/rfc/rfc10008)) is a safe,
373 /// idempotent method whose request content defines the query; remember to
374 /// set a `Content-Type` for the body.
375 ///
376 /// This method returns an instance of `Builder` which can be used to
377 /// create a `Request`.
378 ///
379 /// # Example
380 ///
381 /// ```
382 /// # use rama_http_types::*;
383 ///
384 /// let request = Request::query("https://www.rust-lang.org/")
385 /// .body(())
386 /// .unwrap();
387 /// ```
388 pub fn query<T>(uri: T) -> Builder
389 where
390 T: TryInto<Uri>,
391 <T as TryInto<Uri>>::Error: Into<crate::Error>,
392 {
393 Builder::new().method(Method::QUERY).uri(uri)
394 }
395}
396
397impl<T> Request<T> {
398 /// Creates a new blank `Request` with the body
399 ///
400 /// The component parts of this request will be set to their default, e.g.
401 /// the GET method, no headers, etc.
402 ///
403 /// # Examples
404 ///
405 /// ```
406 /// # use rama_http_types::*;
407 /// let request = Request::new("hello world");
408 ///
409 /// assert_eq!(*request.method(), Method::GET);
410 /// assert_eq!(*request.body(), "hello world");
411 /// ```
412 #[inline]
413 pub fn new(body: T) -> Self {
414 Self {
415 head: Parts::new(),
416 body,
417 }
418 }
419
420 /// Creates a new `Request` with the given components parts and body.
421 ///
422 /// # Examples
423 ///
424 /// ```
425 /// # use rama_http_types::*;
426 /// let request = Request::new("hello world");
427 /// let (mut parts, body) = request.into_parts();
428 /// parts.method = Method::POST;
429 ///
430 /// let request = Request::from_parts(parts, body);
431 /// ```
432 #[inline]
433 pub fn from_parts(parts: Parts, body: T) -> Self {
434 Self { head: parts, body }
435 }
436
437 /// Returns a reference to the associated HTTP method.
438 ///
439 /// # Examples
440 ///
441 /// ```
442 /// # use rama_http_types::*;
443 /// let request: Request<()> = Request::default();
444 /// assert_eq!(*request.method(), Method::GET);
445 /// ```
446 #[inline]
447 pub fn method(&self) -> &Method {
448 &self.head.method
449 }
450
451 /// Returns a mutable reference to the associated HTTP method.
452 ///
453 /// # Examples
454 ///
455 /// ```
456 /// # use rama_http_types::*;
457 /// let mut request: Request<()> = Request::default();
458 /// *request.method_mut() = Method::PUT;
459 /// assert_eq!(*request.method(), Method::PUT);
460 /// ```
461 #[inline]
462 pub fn method_mut(&mut self) -> &mut Method {
463 &mut self.head.method
464 }
465
466 /// Returns a reference to the associated URI.
467 ///
468 /// # Examples
469 ///
470 /// ```
471 /// # use rama_http_types::*;
472 /// let request: Request<()> = Request::default();
473 /// assert_eq!(request.uri().as_str(), "/");
474 /// ```
475 #[inline]
476 pub fn uri(&self) -> &Uri {
477 &self.head.uri
478 }
479
480 /// Get the URI as complete as possible for this request.
481 ///
482 /// Where [`uri`](Self::uri) returns the URI exactly as received (often
483 /// origin-form `/path` for HTTP/1.1), this fills in the scheme and
484 /// authority from the request's effective protocol and authority (URI →
485 /// TLS SNI → `Forwarded` → `Host` header) — a derivation
486 /// callers can treat as a technical detail.
487 #[must_use]
488 pub fn request_uri(&self) -> Uri {
489 use rama_net::{AuthorityInputExt as _, ProtocolInputExt as _};
490
491 let mut uri = self.uri().clone();
492 if let Some(authority) = self.authority() {
493 let protocol = self.protocol().unwrap_or(&rama_net::Protocol::HTTP);
494 let rama_net::address::HostWithOptPort { host, port } =
495 authority.without_default_port_for(Some(protocol));
496 uri.set_scheme(protocol.clone())
497 .set_host(host)
498 .set_port(port);
499 }
500 uri
501 }
502
503 /// Returns a mutable reference to the associated URI.
504 ///
505 /// # Examples
506 ///
507 /// ```
508 /// # use rama_http_types::*;
509 /// let mut request: Request<()> = Request::default();
510 /// *request.uri_mut() = "/hello".parse().unwrap();
511 /// assert_eq!(request.uri().as_str(), "/hello");
512 /// ```
513 #[inline]
514 pub fn uri_mut(&mut self) -> &mut Uri {
515 &mut self.head.uri
516 }
517
518 /// Returns the associated version.
519 ///
520 /// # Examples
521 ///
522 /// ```
523 /// # use rama_http_types::*;
524 /// let request: Request<()> = Request::default();
525 /// assert_eq!(request.version(), Version::HTTP_11);
526 /// ```
527 #[inline]
528 pub fn version(&self) -> Version {
529 self.head.version
530 }
531
532 /// Returns a mutable reference to the associated version.
533 ///
534 /// # Examples
535 ///
536 /// ```
537 /// # use rama_http_types::*;
538 /// let mut request: Request<()> = Request::default();
539 /// *request.version_mut() = Version::HTTP_2;
540 /// assert_eq!(request.version(), Version::HTTP_2);
541 /// ```
542 #[inline]
543 pub fn version_mut(&mut self) -> &mut Version {
544 &mut self.head.version
545 }
546
547 /// Returns a reference to the associated header field map.
548 ///
549 /// # Examples
550 ///
551 /// ```
552 /// # use rama_http_types::*;
553 /// let request: Request<()> = Request::default();
554 /// assert!(request.headers().is_empty());
555 /// ```
556 #[inline]
557 pub fn headers(&self) -> &HeaderMap<HeaderValue> {
558 &self.head.headers
559 }
560
561 /// Returns a mutable reference to the associated header field map.
562 ///
563 /// # Examples
564 ///
565 /// ```
566 /// # use rama_http_types::*;
567 /// # use rama_http_types::header::*;
568 /// let mut request: Request<()> = Request::default();
569 /// request.headers_mut().insert(HOST, HeaderValue::from_static("world"));
570 /// assert!(!request.headers().is_empty());
571 /// ```
572 #[inline]
573 pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
574 &mut self.head.headers
575 }
576
577 /// Returned a cloned of the associated HTTP header.
578 #[inline]
579 pub fn clone_parts(&self) -> Parts {
580 self.head.clone()
581 }
582
583 /// Returns a reference to the associated HTTP body.
584 ///
585 /// # Examples
586 ///
587 /// ```
588 /// # use rama_http_types::*;
589 /// let request: Request<String> = Request::default();
590 /// assert!(request.body().is_empty());
591 /// ```
592 #[inline]
593 pub fn body(&self) -> &T {
594 &self.body
595 }
596
597 /// Returns a mutable reference to the associated HTTP body.
598 ///
599 /// # Examples
600 ///
601 /// ```
602 /// # use rama_http_types::*;
603 /// let mut request: Request<String> = Request::default();
604 /// request.body_mut().push_str("hello world");
605 /// assert!(!request.body().is_empty());
606 /// ```
607 #[inline]
608 pub fn body_mut(&mut self) -> &mut T {
609 &mut self.body
610 }
611
612 /// Consumes the request, returning just the body.
613 ///
614 /// # Examples
615 ///
616 /// ```
617 /// # use rama_http_types::Request;
618 /// let request = Request::new(10);
619 /// let body = request.into_body();
620 /// assert_eq!(body, 10);
621 /// ```
622 #[inline]
623 pub fn into_body(self) -> T {
624 self.body
625 }
626
627 /// Consumes the request returning the head and body parts.
628 ///
629 /// # Examples
630 ///
631 /// ```
632 /// # use rama_http_types::*;
633 /// let request = Request::new(());
634 /// let (parts, body) = request.into_parts();
635 /// assert_eq!(parts.method, Method::GET);
636 /// ```
637 #[inline]
638 pub fn into_parts(self) -> (Parts, T) {
639 (self.head, self.body)
640 }
641
642 /// Consumes the request returning a new request with body mapped to the
643 /// return type of the passed in function.
644 ///
645 /// # Examples
646 ///
647 /// ```
648 /// # use rama_http_types::*;
649 /// let request = Request::builder().body("some string").unwrap();
650 /// let mapped_request: Request<&[u8]> = request.map(|b| {
651 /// assert_eq!(b, "some string");
652 /// b.as_bytes()
653 /// });
654 /// assert_eq!(mapped_request.body(), &"some string".as_bytes());
655 /// ```
656 #[inline]
657 pub fn map<F, U>(self, f: F) -> Request<U>
658 where
659 F: FnOnce(T) -> U,
660 {
661 Request {
662 body: f(self.body),
663 head: self.head,
664 }
665 }
666
667 generate_set_and_with! {
668 pub fn extensions(mut self, extensions: Extensions) -> Self {
669 self.head.extensions = extensions;
670 self
671 }
672 }
673}
674
675impl<T: Default> Default for Request<T> {
676 fn default() -> Self {
677 Self::new(T::default())
678 }
679}
680
681impl<T: fmt::Debug> fmt::Debug for Request<T> {
682 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683 f.debug_struct("Request")
684 .field("method", self.method())
685 .field("uri", self.uri())
686 .field("version", &self.version())
687 .field("headers", self.headers())
688 // omits Extensions because not useful
689 .field("body", self.body())
690 .finish()
691 }
692}
693
694impl<B> ExtensionsRef for Request<B> {
695 fn extensions(&self) -> &Extensions {
696 &self.head.extensions
697 }
698}
699
700impl<B> ClientIp for Request<B> {
701 fn client_ip(&self) -> Option<std::net::IpAddr> {
702 rama_net::client_ip::client_ip(self)
703 }
704}
705
706impl Parts {
707 /// Creates a new default instance of `Parts`
708 fn new() -> Self {
709 Self {
710 method: Method::default(),
711 uri: Uri::from_static("/"),
712 version: Version::default(),
713 headers: HeaderMap::default(),
714 extensions: Extensions::default(),
715 }
716 }
717}
718
719impl fmt::Debug for Parts {
720 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
721 f.debug_struct("Parts")
722 .field("method", &self.method)
723 .field("uri", &self.uri)
724 .field("version", &self.version)
725 .field("headers", &self.headers)
726 // omits Extensions because not useful
727 // omits _priv because not useful
728 .finish()
729 }
730}
731
732impl Builder {
733 /// Creates a new default instance of `Builder` to construct a `Request`.
734 ///
735 /// # Examples
736 ///
737 /// ```
738 /// # use rama_http_types::*;
739 ///
740 /// let req = request::Builder::new()
741 /// .method("POST")
742 /// .body(())
743 /// .unwrap();
744 /// ```
745 #[inline]
746 pub fn new() -> Self {
747 Self::default()
748 }
749
750 #[inline]
751 /// Same as [`Self::new`] but with the given [`Extensions`] to start from.
752 pub fn new_with_extensions(ext: Extensions) -> Self {
753 Self {
754 inner: Ok(Parts {
755 method: Method::default(),
756 uri: Uri::from_static("/"),
757 version: Version::default(),
758 headers: HeaderMap::default(),
759 extensions: ext,
760 }),
761 }
762 }
763
764 /// Set the HTTP method for this request.
765 ///
766 /// By default this is `GET`.
767 ///
768 /// # Examples
769 ///
770 /// ```
771 /// # use rama_http_types::*;
772 ///
773 /// let req = Request::builder()
774 /// .method("POST")
775 /// .body(())
776 /// .unwrap();
777 /// ```
778 pub fn method<T>(self, method: T) -> Self
779 where
780 T: TryInto<Method>,
781 <T as TryInto<Method>>::Error: Into<crate::Error>,
782 {
783 self.and_then(move |mut head| {
784 let method = method.try_into().map_err(Into::into)?;
785 head.method = method;
786 Ok(head)
787 })
788 }
789
790 /// Get the HTTP Method for this request.
791 ///
792 /// By default this is `GET`. If builder has error, returns None.
793 ///
794 /// # Examples
795 ///
796 /// ```
797 /// # use rama_http_types::*;
798 ///
799 /// let mut req = Request::builder();
800 /// assert_eq!(req.method_ref(),Some(&Method::GET));
801 ///
802 /// req = req.method("POST");
803 /// assert_eq!(req.method_ref(),Some(&Method::POST));
804 /// ```
805 pub fn method_ref(&self) -> Option<&Method> {
806 self.inner.as_ref().ok().map(|h| &h.method)
807 }
808
809 /// Set the URI for this request.
810 ///
811 /// By default this is `/`.
812 ///
813 /// # Examples
814 ///
815 /// ```
816 /// # use rama_http_types::*;
817 ///
818 /// let req = Request::builder()
819 /// .uri("https://www.rust-lang.org/")
820 /// .body(())
821 /// .unwrap();
822 /// ```
823 pub fn uri<T>(self, uri: T) -> Self
824 where
825 T: TryInto<Uri>,
826 <T as TryInto<Uri>>::Error: Into<crate::Error>,
827 {
828 self.and_then(move |mut head| {
829 head.uri = uri.try_into().map_err(Into::into)?;
830 Ok(head)
831 })
832 }
833
834 /// Get the URI for this request
835 ///
836 /// By default this is `/`.
837 ///
838 /// # Examples
839 ///
840 /// ```
841 /// # use rama_http_types::*;
842 ///
843 /// let mut req = Request::builder();
844 /// assert_eq!(req.uri_ref().unwrap().as_str(), "/");
845 ///
846 /// req = req.uri("https://www.rust-lang.org/");
847 /// assert_eq!(req.uri_ref().unwrap().as_str(), "https://www.rust-lang.org/");
848 /// ```
849 pub fn uri_ref(&self) -> Option<&Uri> {
850 self.inner.as_ref().ok().map(|h| &h.uri)
851 }
852
853 /// Set the HTTP version for this request.
854 ///
855 /// By default this is HTTP/1.1
856 ///
857 /// # Examples
858 ///
859 /// ```
860 /// # use rama_http_types::*;
861 ///
862 /// let req = Request::builder()
863 /// .version(Version::HTTP_2)
864 /// .body(())
865 /// .unwrap();
866 /// ```
867 pub fn version(self, version: Version) -> Self {
868 self.and_then(move |mut head| {
869 head.version = version;
870 Ok(head)
871 })
872 }
873
874 /// Get the HTTP version for this request
875 ///
876 /// By default this is HTTP/1.1.
877 ///
878 /// # Examples
879 ///
880 /// ```
881 /// # use rama_http_types::*;
882 ///
883 /// let mut req = Request::builder();
884 /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_11 );
885 ///
886 /// req = req.version(Version::HTTP_2);
887 /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_2 );
888 /// ```
889 pub fn version_ref(&self) -> Option<&Version> {
890 self.inner.as_ref().ok().map(|h| &h.version)
891 }
892
893 /// Appends a header to this request builder.
894 ///
895 /// This function will append the provided key/value as a header to the
896 /// internal `HeaderMap` being constructed. Essentially this is equivalent
897 /// to calling `HeaderMap::append`.
898 ///
899 /// # Examples
900 ///
901 /// ```
902 /// # use rama_http_types::*;
903 /// # use rama_http_types::header::HeaderValue;
904 ///
905 /// let req = Request::builder()
906 /// .header("Accept", "text/html")
907 /// .header("X-Custom-Foo", "bar")
908 /// .body(())
909 /// .unwrap();
910 /// ```
911 pub fn header<K, V>(self, key: K, value: V) -> Self
912 where
913 K: TryInto<HeaderName>,
914 <K as TryInto<HeaderName>>::Error: Into<crate::Error>,
915 V: TryInto<HeaderValue>,
916 <V as TryInto<HeaderValue>>::Error: Into<crate::Error>,
917 {
918 self.and_then(move |mut head| {
919 let name = key.try_into().map_err(Into::into)?;
920 let value = value.try_into().map_err(Into::into)?;
921 head.headers.try_append(name, value)?;
922 Ok(head)
923 })
924 }
925
926 /// Get header on this request builder.
927 /// when builder has error returns None
928 ///
929 /// # Example
930 ///
931 /// ```
932 /// # use rama_http_types::Request;
933 /// let req = Request::builder()
934 /// .header("Accept", "text/html")
935 /// .header("X-Custom-Foo", "bar");
936 /// let headers = req.headers_ref().unwrap();
937 /// assert_eq!( headers["Accept"], "text/html" );
938 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
939 /// ```
940 pub fn headers_ref(&self) -> Option<&HeaderMap<HeaderValue>> {
941 self.inner.as_ref().ok().map(|h| &h.headers)
942 }
943
944 /// Get headers on this request builder.
945 ///
946 /// When builder has error returns None.
947 ///
948 /// # Example
949 ///
950 /// ```
951 /// # use rama_http_types::{header::HeaderValue, Request};
952 /// let mut req = Request::builder();
953 /// {
954 /// let headers = req.headers_mut().unwrap();
955 /// headers.insert("Accept", HeaderValue::from_static("text/html"));
956 /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
957 /// }
958 /// let headers = req.headers_ref().unwrap();
959 /// assert_eq!( headers["Accept"], "text/html" );
960 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
961 /// ```
962 pub fn headers_mut(&mut self) -> Option<&mut HeaderMap<HeaderValue>> {
963 self.inner.as_mut().ok().map(|h| &mut h.headers)
964 }
965
966 /// Adds an extension to this builder
967 ///
968 /// # Examples
969 ///
970 /// ```
971 /// # use rama_http_types::Request;
972 /// # use rama_core::extensions::{Extension, ExtensionsRef as _};
973 ///
974 /// #[derive(Debug, Clone, PartialEq)]
975 /// struct MyExtension(&'static str);
976 /// impl Extension for MyExtension {}
977 ///
978 /// let req = Request::builder()
979 /// .extension(MyExtension("My Extension"))
980 /// .body(())
981 /// .unwrap();
982 ///
983 /// assert_eq!(req.extensions().get_ref::<MyExtension>(),
984 /// Some(&MyExtension("My Extension")));
985 /// ```
986 pub fn extension<T>(self, extension: T) -> Self
987 where
988 T: Extension,
989 {
990 self.and_then(move |head| {
991 head.extensions.insert(extension);
992 Ok(head)
993 })
994 }
995
996 /// Get a reference to the extensions for this request builder.
997 ///
998 /// If the builder has an error, this returns `None`.
999 ///
1000 /// # Example
1001 ///
1002 /// ```
1003 /// # use rama_http_types::Request;
1004 /// # use rama_core::extensions::Extension;
1005 /// #[derive(Debug, Clone, PartialEq)]
1006 /// struct MyExtension(&'static str);
1007 /// impl Extension for MyExtension {}
1008 ///
1009 /// #[derive(Debug, Clone, PartialEq)]
1010 /// struct MyCount(u32);
1011 /// impl Extension for MyCount {}
1012 ///
1013 /// let req = Request::builder().extension(MyExtension("My Extension")).extension(MyCount(5));
1014 /// let extensions = req.extensions().unwrap();
1015 /// assert_eq!(extensions.get_ref::<MyExtension>(), Some(&MyExtension("My Extension")));
1016 /// assert_eq!(extensions.get_ref::<MyCount>(), Some(&MyCount(5)));
1017 /// ```
1018 pub fn extensions(&self) -> Option<&Extensions> {
1019 self.inner.as_ref().ok().map(|h| &h.extensions)
1020 }
1021
1022 /// "Consumes" this builder, using the provided `body` to return a
1023 /// constructed `Request`.
1024 ///
1025 /// # Errors
1026 ///
1027 /// This function may return an error if any previously configured argument
1028 /// failed to parse or get converted to the internal representation. For
1029 /// example if an invalid `head` was specified via `header("Foo",
1030 /// "Bar\r\n")` the error will be returned when this function is called
1031 /// rather than when `header` was called.
1032 ///
1033 /// # Examples
1034 ///
1035 /// ```
1036 /// # use rama_http_types::*;
1037 ///
1038 /// let request = Request::builder()
1039 /// .body(())
1040 /// .unwrap();
1041 /// ```
1042 pub fn body<T>(self, body: T) -> Result<Request<T>> {
1043 self.inner.map(move |head| Request { head, body })
1044 }
1045
1046 // private
1047
1048 fn and_then<F>(self, func: F) -> Self
1049 where
1050 F: FnOnce(Parts) -> Result<Parts>,
1051 {
1052 Self {
1053 inner: self.inner.and_then(func),
1054 }
1055 }
1056}
1057
1058impl Default for Builder {
1059 #[inline]
1060 fn default() -> Self {
1061 Self {
1062 inner: Ok(Parts::new()),
1063 }
1064 }
1065}
1066
1067/// [`HttpRequestParts`] is used in places where we don't need the [`ReqBody`] of the [`HttpRequest`]
1068///
1069/// In those places we need to support using [`HttpRequest`] and [`Parts`]. By using
1070/// this trait we can support both types behind a single generic that implements this trait.
1071///
1072/// [`ReqBody`]: crate::body::StreamingBody
1073/// [`HttpRequest`]: crate::Request
1074pub trait HttpRequestParts: ExtensionsRef {
1075 fn method(&self) -> &Method;
1076 fn uri(&self) -> &Uri;
1077 fn version(&self) -> Version;
1078 fn headers(&self) -> &HeaderMap<HeaderValue>;
1079}
1080
1081impl<T: HttpRequestParts> HttpRequestParts for &T {
1082 #[inline(always)]
1083 fn method(&self) -> &Method {
1084 (*self).method()
1085 }
1086
1087 #[inline(always)]
1088 fn uri(&self) -> &Uri {
1089 (*self).uri()
1090 }
1091
1092 #[inline(always)]
1093 fn version(&self) -> Version {
1094 (*self).version()
1095 }
1096
1097 #[inline(always)]
1098 fn headers(&self) -> &HeaderMap<HeaderValue> {
1099 (*self).headers()
1100 }
1101}
1102
1103impl<T: HttpRequestParts> HttpRequestParts for &mut T {
1104 #[inline(always)]
1105 fn method(&self) -> &Method {
1106 (**self).method()
1107 }
1108
1109 fn uri(&self) -> &Uri {
1110 (**self).uri()
1111 }
1112
1113 fn version(&self) -> Version {
1114 (**self).version()
1115 }
1116
1117 fn headers(&self) -> &HeaderMap<HeaderValue> {
1118 (**self).headers()
1119 }
1120}
1121
1122impl<Body> HttpRequestParts for Request<Body> {
1123 fn method(&self) -> &Method {
1124 self.method()
1125 }
1126
1127 fn uri(&self) -> &Uri {
1128 self.uri()
1129 }
1130
1131 fn version(&self) -> Version {
1132 self.version()
1133 }
1134
1135 fn headers(&self) -> &HeaderMap<HeaderValue> {
1136 self.headers()
1137 }
1138}
1139
1140impl HttpRequestParts for Parts {
1141 fn method(&self) -> &Method {
1142 &self.method
1143 }
1144
1145 fn uri(&self) -> &Uri {
1146 &self.uri
1147 }
1148
1149 fn version(&self) -> Version {
1150 self.version
1151 }
1152
1153 fn headers(&self) -> &HeaderMap<HeaderValue> {
1154 &self.headers
1155 }
1156}
1157
1158/// Same as [`HttpRequestParts`] but also adding mutable access
1159pub trait HttpRequestPartsMut: HttpRequestParts + ExtensionsRef {
1160 fn method_mut(&mut self) -> &mut Method;
1161 fn uri_mut(&mut self) -> &mut Uri;
1162 fn version_mut(&mut self) -> &mut Version;
1163 fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue>;
1164}
1165
1166impl<T: HttpRequestPartsMut> HttpRequestPartsMut for &mut T {
1167 fn method_mut(&mut self) -> &mut Method {
1168 (*self).method_mut()
1169 }
1170
1171 fn uri_mut(&mut self) -> &mut Uri {
1172 (*self).uri_mut()
1173 }
1174
1175 fn version_mut(&mut self) -> &mut Version {
1176 (*self).version_mut()
1177 }
1178
1179 fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
1180 (*self).headers_mut()
1181 }
1182}
1183
1184impl<Body> HttpRequestPartsMut for Request<Body> {
1185 fn method_mut(&mut self) -> &mut Method {
1186 self.method_mut()
1187 }
1188
1189 fn uri_mut(&mut self) -> &mut Uri {
1190 self.uri_mut()
1191 }
1192
1193 fn version_mut(&mut self) -> &mut Version {
1194 self.version_mut()
1195 }
1196
1197 fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
1198 self.headers_mut()
1199 }
1200}
1201
1202impl HttpRequestPartsMut for Parts {
1203 fn method_mut(&mut self) -> &mut Method {
1204 &mut self.method
1205 }
1206
1207 fn uri_mut(&mut self) -> &mut Uri {
1208 &mut self.uri
1209 }
1210
1211 fn version_mut(&mut self) -> &mut Version {
1212 &mut self.version
1213 }
1214
1215 fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
1216 &mut self.headers
1217 }
1218}
1219
1220#[cfg(test)]
1221mod tests {
1222 use super::*;
1223
1224 #[test]
1225 fn it_can_map_a_body_from_one_type_to_another() {
1226 let request = Request::builder().body("some string").unwrap();
1227 let mapped_request = request.map(|s| {
1228 assert_eq!(s, "some string");
1229 123u32
1230 });
1231 assert_eq!(mapped_request.body(), &123u32);
1232 }
1233
1234 #[test]
1235 fn test_request_uri() {
1236 use crate::header::HOST;
1237 use rama_net::{
1238 address::Domain,
1239 forwarded::{Forwarded, ForwardedElement},
1240 };
1241
1242 for (request, expected_uri_str) in [
1243 (Request::builder().uri("/foo").body(()).unwrap(), "/foo"),
1244 (
1245 Request::builder()
1246 .uri("/foo")
1247 .header(HOST, "example.com")
1248 .body(())
1249 .unwrap(),
1250 "http://example.com/foo",
1251 ),
1252 (
1253 Request::builder()
1254 .uri("/foo")
1255 .extension(Forwarded::new(ForwardedElement::new_forwarded_host(
1256 Domain::from_static("example.com"),
1257 )))
1258 .body(())
1259 .unwrap(),
1260 "http://example.com/foo",
1261 ),
1262 (
1263 Request::builder()
1264 .uri("http://example.com/foo")
1265 .body(())
1266 .unwrap(),
1267 "http://example.com/foo",
1268 ),
1269 (
1270 Request::builder()
1271 .uri("https://example.com/foo")
1272 .body(())
1273 .unwrap(),
1274 "https://example.com/foo",
1275 ),
1276 (
1277 Request::builder()
1278 .uri(Uri::parse_authority_form("WwW.ExamplE.COM").unwrap())
1279 .body(())
1280 .unwrap(),
1281 // native Uri preserves the empty path (no forced trailing `/`)
1282 "http://WwW.ExamplE.COM",
1283 ),
1284 ] {
1285 let s = request.request_uri().to_string();
1286 assert_eq!(s, expected_uri_str, "request: {request:?}");
1287 }
1288 }
1289}