Skip to main content

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}