axol_http/request.rs
1use std::{any::Any, convert::Infallible};
2
3use http::Error as HttpError;
4use thiserror::Error;
5
6use crate::{header::HeaderMap, method::MethodParseError, Body, Extensions, Method, Uri, Version};
7
8/// Represents an HTTP request.
9///
10/// An HTTP request consists of a head and a optional body.
11///
12/// # Examples
13///
14/// Creating a `Request` to send
15///
16/// ```no_run
17/// use axol_http::{Request, Response};
18///
19/// let mut request = Request::builder()
20/// .uri("https://www.rust-lang.org/")
21/// .header("User-Agent", "my-awesome-agent/1.0");
22///
23/// if needs_awesome_header() {
24/// request = request.header("Awesome", "yes");
25/// }
26///
27/// let response = send(request.body(()).unwrap());
28///
29/// # fn needs_awesome_header() -> bool {
30/// # true
31/// # }
32/// #
33/// fn send(req: Request<()>) -> Response<()> {
34/// // ...
35/// # panic!()
36/// }
37/// ```
38///
39/// Inspecting a request to see what was sent.
40///
41/// ```
42/// use axol_http::{Request, Response, StatusCode};
43///
44/// fn respond_to(req: Request<()>) -> axol_http::Result<Response<()>> {
45/// if req.uri() != "/awesome-url" {
46/// return Response::builder()
47/// .status(StatusCode::NOT_FOUND)
48/// .body(())
49/// }
50///
51/// let has_awesome_header = req.headers().contains_key("Awesome");
52/// let body = req.body();
53///
54/// // ...
55/// # panic!()
56/// }
57/// ```
58///
59/// Deserialize a request of bytes via json:
60///
61/// ```
62/// # extern crate serde;
63/// # extern crate serde_json;
64/// # extern crate http;
65/// use axol_http::Request;
66/// use serde::de;
67///
68/// fn deserialize<T>(req: Request<Vec<u8>>) -> serde_json::Result<Request<T>>
69/// where for<'de> T: de::Deserialize<'de>,
70/// {
71/// let (parts, body) = req.into_parts();
72/// let body = serde_json::from_slice(&body)?;
73/// Ok(Request::from_parts(parts, body))
74/// }
75/// #
76/// # fn main() {}
77/// ```
78///
79/// Or alternatively, serialize the body of a request to json
80///
81/// ```
82/// # extern crate serde;
83/// # extern crate serde_json;
84/// # extern crate http;
85/// use axol_http::Request;
86/// use serde::ser;
87///
88/// fn serialize<T>(req: Request<T>) -> serde_json::Result<Request<Vec<u8>>>
89/// where T: ser::Serialize,
90/// {
91/// let (parts, body) = req.into_parts();
92/// let body = serde_json::to_vec(&body)?;
93/// Ok(Request::from_parts(parts, body))
94/// }
95/// #
96/// # fn main() {}
97/// ```
98#[derive(Debug, Default)]
99pub struct Request {
100 /// The request's method
101 pub method: Method,
102
103 /// The request's URI
104 pub uri: Uri,
105
106 /// The request's version
107 pub version: Version,
108
109 /// The request's headers. All headers are always lowercased.
110 pub headers: HeaderMap,
111
112 /// The request's extensions
113 pub extensions: Extensions,
114
115 /// The request's body
116 pub body: Body,
117}
118
119/// Component parts of an HTTP `Request`
120///
121/// The HTTP request head consists of a method, uri, version, and a set of
122/// header fields.
123#[derive(Debug, Default)]
124pub struct RequestParts {
125 /// The request's method
126 pub method: Method,
127
128 /// The request's URI
129 pub uri: Uri,
130
131 /// The request's version
132 pub version: Version,
133
134 /// The request's headers. All headers are always lowercased.
135 pub headers: HeaderMap,
136
137 /// The request's extensions
138 pub extensions: Extensions,
139}
140
141impl RequestParts {
142 pub fn as_ref(&self) -> RequestPartsRef<'_> {
143 RequestPartsRef {
144 method: self.method,
145 uri: &self.uri,
146 version: self.version,
147 headers: &self.headers,
148 extensions: &self.extensions,
149 }
150 }
151}
152
153#[derive(Debug, Clone, Copy)]
154pub struct RequestPartsRef<'a> {
155 /// The request's method
156 pub method: Method,
157
158 /// The request's URI
159 pub uri: &'a Uri,
160
161 /// The request's version
162 pub version: Version,
163
164 /// The request's headers. All headers are always lowercased.
165 pub headers: &'a HeaderMap,
166
167 /// The request's extensions.
168 pub extensions: &'a Extensions,
169}
170
171impl<'a> RequestPartsRef<'a> {
172 pub fn into_owned(&self) -> RequestParts {
173 RequestParts {
174 method: self.method,
175 uri: self.uri.clone(),
176 version: self.version,
177 headers: self.headers.clone(),
178 extensions: self.extensions.clone(),
179 }
180 }
181}
182
183impl Request {
184 pub fn parts(&self) -> RequestPartsRef<'_> {
185 RequestPartsRef {
186 method: self.method,
187 uri: &self.uri,
188 version: self.version,
189 headers: &self.headers,
190 extensions: &self.extensions,
191 }
192 }
193
194 /// Creates a new builder-style object to manufacture a `Request`
195 ///
196 /// This method returns an instance of `Builder` which can be used to
197 /// create a `Request`.
198 ///
199 /// # Examples
200 ///
201 /// ```
202 /// # use axol_http::*;
203 /// let request = Request::builder()
204 /// .method("GET")
205 /// .uri("https://www.rust-lang.org/")
206 /// .header("X-Custom-Foo", "Bar")
207 /// .body(())
208 /// .unwrap();
209 /// ```
210 pub fn builder() -> Builder {
211 Builder::new()
212 }
213
214 /// Creates a new `Builder` initialized with a GET method and the given URI.
215 ///
216 /// This method returns an instance of `Builder` which can be used to
217 /// create a `Request`.
218 ///
219 /// # Example
220 ///
221 /// ```
222 /// # use axol_http::*;
223 ///
224 /// let request = Request::get("https://www.rust-lang.org/")
225 /// .body(())
226 /// .unwrap();
227 /// ```
228 pub fn get<T>(uri: T) -> Builder
229 where
230 Uri: TryFrom<T>,
231 <Uri as TryFrom<T>>::Error: Into<HttpError>,
232 {
233 Builder::new().method(Method::Get).uri(uri)
234 }
235
236 /// Creates a new `Builder` initialized with a PUT method and the given URI.
237 ///
238 /// This method returns an instance of `Builder` which can be used to
239 /// create a `Request`.
240 ///
241 /// # Example
242 ///
243 /// ```
244 /// # use axol_http::*;
245 ///
246 /// let request = Request::put("https://www.rust-lang.org/")
247 /// .body(())
248 /// .unwrap();
249 /// ```
250 pub fn put<T>(uri: T) -> Builder
251 where
252 Uri: TryFrom<T>,
253 <Uri as TryFrom<T>>::Error: Into<HttpError>,
254 {
255 Builder::new().method(Method::Put).uri(uri)
256 }
257
258 /// Creates a new `Builder` initialized with a POST method and the given URI.
259 ///
260 /// This method returns an instance of `Builder` which can be used to
261 /// create a `Request`.
262 ///
263 /// # Example
264 ///
265 /// ```
266 /// # use axol_http::*;
267 ///
268 /// let request = Request::post("https://www.rust-lang.org/")
269 /// .body(())
270 /// .unwrap();
271 /// ```
272 pub fn post<T>(uri: T) -> Builder
273 where
274 Uri: TryFrom<T>,
275 <Uri as TryFrom<T>>::Error: Into<HttpError>,
276 {
277 Builder::new().method(Method::Post).uri(uri)
278 }
279
280 /// Creates a new `Builder` initialized with a DELETE method and the given URI.
281 ///
282 /// This method returns an instance of `Builder` which can be used to
283 /// create a `Request`.
284 ///
285 /// # Example
286 ///
287 /// ```
288 /// # use axol_http::*;
289 ///
290 /// let request = Request::delete("https://www.rust-lang.org/")
291 /// .body(())
292 /// .unwrap();
293 /// ```
294 pub fn delete<T>(uri: T) -> Builder
295 where
296 Uri: TryFrom<T>,
297 <Uri as TryFrom<T>>::Error: Into<HttpError>,
298 {
299 Builder::new().method(Method::Delete).uri(uri)
300 }
301
302 /// Creates a new `Builder` initialized with an OPTIONS method and the given URI.
303 ///
304 /// This method returns an instance of `Builder` which can be used to
305 /// create a `Request`.
306 ///
307 /// # Example
308 ///
309 /// ```
310 /// # use axol_http::*;
311 ///
312 /// let request = Request::options("https://www.rust-lang.org/")
313 /// .body(())
314 /// .unwrap();
315 /// # assert_eq!(*request.method(), Method::OPTIONS);
316 /// ```
317 pub fn options<T>(uri: T) -> Builder
318 where
319 Uri: TryFrom<T>,
320 <Uri as TryFrom<T>>::Error: Into<HttpError>,
321 {
322 Builder::new().method(Method::Options).uri(uri)
323 }
324
325 /// Creates a new `Builder` initialized with a HEAD method and the given URI.
326 ///
327 /// This method returns an instance of `Builder` which can be used to
328 /// create a `Request`.
329 ///
330 /// # Example
331 ///
332 /// ```
333 /// # use axol_http::*;
334 ///
335 /// let request = Request::head("https://www.rust-lang.org/")
336 /// .body(())
337 /// .unwrap();
338 /// ```
339 pub fn head<T>(uri: T) -> Builder
340 where
341 Uri: TryFrom<T>,
342 <Uri as TryFrom<T>>::Error: Into<HttpError>,
343 {
344 Builder::new().method(Method::Head).uri(uri)
345 }
346
347 /// Creates a new `Builder` initialized with a CONNECT method and the given URI.
348 ///
349 /// This method returns an instance of `Builder` which can be used to
350 /// create a `Request`.
351 ///
352 /// # Example
353 ///
354 /// ```
355 /// # use axol_http::*;
356 ///
357 /// let request = Request::connect("https://www.rust-lang.org/")
358 /// .body(())
359 /// .unwrap();
360 /// ```
361 pub fn connect<T>(uri: T) -> Builder
362 where
363 Uri: TryFrom<T>,
364 <Uri as TryFrom<T>>::Error: Into<HttpError>,
365 {
366 Builder::new().method(Method::Connect).uri(uri)
367 }
368
369 /// Creates a new `Builder` initialized with a PATCH method and the given URI.
370 ///
371 /// This method returns an instance of `Builder` which can be used to
372 /// create a `Request`.
373 ///
374 /// # Example
375 ///
376 /// ```
377 /// # use axol_http::*;
378 ///
379 /// let request = Request::patch("https://www.rust-lang.org/")
380 /// .body(())
381 /// .unwrap();
382 /// ```
383 pub fn patch<T>(uri: T) -> Builder
384 where
385 Uri: TryFrom<T>,
386 <Uri as TryFrom<T>>::Error: Into<HttpError>,
387 {
388 Builder::new().method(Method::Patch).uri(uri)
389 }
390
391 /// Creates a new `Builder` initialized with a TRACE method and the given URI.
392 ///
393 /// This method returns an instance of `Builder` which can be used to
394 /// create a `Request`.
395 ///
396 /// # Example
397 ///
398 /// ```
399 /// # use axol_http::*;
400 ///
401 /// let request = Request::trace("https://www.rust-lang.org/")
402 /// .body(())
403 /// .unwrap();
404 /// ```
405 pub fn trace<T>(uri: T) -> Builder
406 where
407 Uri: TryFrom<T>,
408 <Uri as TryFrom<T>>::Error: Into<HttpError>,
409 {
410 Builder::new().method(Method::Trace).uri(uri)
411 }
412
413 /// Creates a new blank `Request` with the body
414 ///
415 /// The component parts of this request will be set to their default, e.g.
416 /// the GET method, no headers, etc.
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// # use axol_http::*;
422 /// let request = Request::new("hello world");
423 ///
424 /// assert_eq!(*request.method(), Method::GET);
425 /// assert_eq!(*request.body(), "hello world");
426 /// ```
427 pub fn new(body: impl Into<Body>) -> Request {
428 Self::from_parts(Default::default(), body)
429 }
430
431 /// Creates a new `Request` with the given components parts and body.
432 ///
433 /// # Examples
434 ///
435 /// ```
436 /// # use axol_http::*;
437 /// let request = Request::new("hello world");
438 /// let (mut parts, body) = request.into_parts();
439 /// parts.method = Method::POST;
440 ///
441 /// let request = Request::from_parts(parts, body);
442 /// ```
443 pub fn from_parts(parts: RequestParts, body: impl Into<Body>) -> Request {
444 Request {
445 method: parts.method,
446 uri: parts.uri,
447 version: parts.version,
448 headers: parts.headers,
449 extensions: parts.extensions,
450 body: body.into(),
451 }
452 }
453
454 /// Consumes the request returning the head and body parts.
455 ///
456 /// # Examples
457 ///
458 /// ```
459 /// # use axol_http::*;
460 /// let request = Request::new(());
461 /// let (parts, body) = request.into_parts();
462 /// assert_eq!(parts.method, Method::GET);
463 /// ```
464 pub fn into_parts(self) -> (RequestParts, Body) {
465 (
466 RequestParts {
467 method: self.method,
468 uri: self.uri,
469 version: self.version,
470 headers: self.headers,
471 extensions: self.extensions,
472 },
473 self.body,
474 )
475 }
476}
477
478#[derive(Error, Debug)]
479pub enum RequestBuilderError {
480 #[error("")]
481 Infallible(#[from] Infallible),
482 #[error("method parse error: {0}")]
483 MethodParse(#[from] MethodParseError),
484 #[error("http error: {0}")]
485 Http(#[from] HttpError),
486}
487
488/// An HTTP request builder
489///
490/// This type can be used to construct an instance or `Request`
491/// through a builder-like pattern.
492#[derive(Debug)]
493pub struct Builder {
494 inner: Result<Request, RequestBuilderError>,
495}
496
497impl Builder {
498 /// Creates a new default instance of `Builder` to construct a `Request`.
499 ///
500 /// # Examples
501 ///
502 /// ```
503 /// # use axol_http::*;
504 ///
505 /// let req = request::Builder::new()
506 /// .method("POST")
507 /// .body(())
508 /// .unwrap();
509 /// ```
510 pub fn new() -> Builder {
511 Builder::default()
512 }
513
514 /// Set the HTTP method for this request.
515 ///
516 /// This function will configure the HTTP method of the `Request` that will
517 /// be returned from `Builder::build`.
518 ///
519 /// By default this is `GET`.
520 ///
521 /// # Examples
522 ///
523 /// ```
524 /// # use axol_http::*;
525 ///
526 /// let req = Request::builder()
527 /// .method("POST")
528 /// .body(())
529 /// .unwrap();
530 /// ```
531 pub fn method(self, method: Method) -> Builder {
532 self.and_then(move |mut head| {
533 head.method = method;
534 Ok(head)
535 })
536 }
537
538 /// Get the HTTP Method for this request.
539 ///
540 /// By default this is `GET`. If builder has error, returns None.
541 ///
542 /// # Examples
543 ///
544 /// ```
545 /// # use axol_http::*;
546 ///
547 /// let mut req = Request::builder();
548 /// assert_eq!(req.method_ref(),Some(&Method::GET));
549 ///
550 /// req = req.method("POST");
551 /// assert_eq!(req.method_ref(),Some(&Method::POST));
552 /// ```
553 pub fn method_ref(&self) -> Option<Method> {
554 self.inner.as_ref().ok().map(|h| h.method)
555 }
556
557 /// Set the URI for this request.
558 ///
559 /// This function will configure the URI of the `Request` that will
560 /// be returned from `Builder::build`.
561 ///
562 /// By default this is `/`.
563 ///
564 /// # Examples
565 ///
566 /// ```
567 /// # use axol_http::*;
568 ///
569 /// let req = Request::builder()
570 /// .uri("https://www.rust-lang.org/")
571 /// .body(())
572 /// .unwrap();
573 /// ```
574 pub fn uri<T>(self, uri: T) -> Builder
575 where
576 Uri: TryFrom<T>,
577 <Uri as TryFrom<T>>::Error: Into<HttpError>,
578 {
579 self.and_then(move |mut head| {
580 head.uri = TryFrom::try_from(uri).map_err(Into::into)?;
581 Ok(head)
582 })
583 }
584
585 /// Get the URI for this request
586 ///
587 /// By default this is `/`.
588 ///
589 /// # Examples
590 ///
591 /// ```
592 /// # use axol_http::*;
593 ///
594 /// let mut req = Request::builder();
595 /// assert_eq!(req.uri_ref().unwrap(), "/" );
596 ///
597 /// req = req.uri("https://www.rust-lang.org/");
598 /// assert_eq!(req.uri_ref().unwrap(), "https://www.rust-lang.org/" );
599 /// ```
600 pub fn uri_ref(&self) -> Option<&Uri> {
601 self.inner.as_ref().ok().map(|h| &h.uri)
602 }
603
604 /// Set the HTTP version for this request.
605 ///
606 /// This function will configure the HTTP version of the `Request` that
607 /// will be returned from `Builder::build`.
608 ///
609 /// By default this is HTTP/1.1
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// # use axol_http::*;
615 ///
616 /// let req = Request::builder()
617 /// .version(Version::HTTP_2)
618 /// .body(())
619 /// .unwrap();
620 /// ```
621 pub fn version(self, version: Version) -> Builder {
622 self.and_then(move |mut head| {
623 head.version = version;
624 Ok(head)
625 })
626 }
627
628 /// Get the HTTP version for this request
629 ///
630 /// By default this is HTTP/1.1.
631 ///
632 /// # Examples
633 ///
634 /// ```
635 /// # use axol_http::*;
636 ///
637 /// let mut req = Request::builder();
638 /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_11 );
639 ///
640 /// req = req.version(Version::HTTP_2);
641 /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_2 );
642 /// ```
643 pub fn version_ref(&self) -> Option<&Version> {
644 self.inner.as_ref().ok().map(|h| &h.version)
645 }
646
647 /// Appends a header to this request builder.
648 ///
649 /// This function will append the provided key/value as a header to the
650 /// internal `HeaderMap` being constructed. Essentially this is equivalent
651 /// to calling `HeaderMap::append`.
652 ///
653 /// # Examples
654 ///
655 /// ```
656 /// # use axol_http::*;
657 /// # use axol_http::header::HeaderValue;
658 ///
659 /// let req = Request::builder()
660 /// .header("Accept", "text/html")
661 /// .header("X-Custom-Foo", "bar")
662 /// .body(())
663 /// .unwrap();
664 /// ```
665 pub fn header(self, name: impl AsRef<str>, value: impl Into<String>) -> Builder {
666 self.and_then(move |mut head| {
667 head.headers.insert(name, value);
668 Ok(head)
669 })
670 }
671
672 /// Get header on this request builder.
673 /// when builder has error returns None
674 ///
675 /// # Example
676 ///
677 /// ```
678 /// # use axol_http::Request;
679 /// let req = Request::builder()
680 /// .header("Accept", "text/html")
681 /// .header("X-Custom-Foo", "bar");
682 /// let headers = req.headers_ref().unwrap();
683 /// assert_eq!( headers["Accept"], "text/html" );
684 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
685 /// ```
686 pub fn headers_ref(&self) -> Option<&HeaderMap> {
687 self.inner.as_ref().ok().map(|h| &h.headers)
688 }
689
690 /// Get headers on this request builder.
691 ///
692 /// When builder has error returns None.
693 ///
694 /// # Example
695 ///
696 /// ```
697 /// # use axol_http::{header::HeaderValue, Request};
698 /// let mut req = Request::builder();
699 /// {
700 /// let headers = req.headers_mut().unwrap();
701 /// headers.insert("Accept", HeaderValue::from_static("text/html"));
702 /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
703 /// }
704 /// let headers = req.headers_ref().unwrap();
705 /// assert_eq!( headers["Accept"], "text/html" );
706 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
707 /// ```
708 pub fn headers_mut(&mut self) -> Option<&mut HeaderMap> {
709 self.inner.as_mut().ok().map(|h| &mut h.headers)
710 }
711
712 /// Adds an extension to this builder
713 ///
714 /// # Examples
715 ///
716 /// ```
717 /// # use axol_http::*;
718 ///
719 /// let req = Request::builder()
720 /// .extension("My Extension")
721 /// .body(())
722 /// .unwrap();
723 ///
724 /// assert_eq!(req.extensions().get::<&'static str>(),
725 /// Some(&"My Extension"));
726 /// ```
727 pub fn extension<T>(self, extension: T) -> Builder
728 where
729 T: Any + Send + Sync + 'static,
730 {
731 self.and_then(move |head| {
732 head.extensions.insert(extension);
733 Ok(head)
734 })
735 }
736
737 /// Get a reference to the extensions for this request builder.
738 ///
739 /// If the builder has an error, this returns `None`.
740 ///
741 /// # Example
742 ///
743 /// ```
744 /// # use axol_http::Request;
745 /// let req = Request::builder().extension("My Extension").extension(5u32);
746 /// let extensions = req.extensions_ref().unwrap();
747 /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension"));
748 /// assert_eq!(extensions.get::<u32>(), Some(&5u32));
749 /// ```
750 pub fn extensions(&self) -> Option<&Extensions> {
751 self.inner.as_ref().ok().map(|h| &h.extensions)
752 }
753
754 pub fn extensions_mut(&mut self) -> Option<&mut Extensions> {
755 self.inner.as_mut().ok().map(|h| &mut h.extensions)
756 }
757
758 /// "Consumes" this builder, using the provided `body` to return a
759 /// constructed `Request`.
760 ///
761 /// # Errors
762 ///
763 /// This function may return an error if any previously configured argument
764 /// failed to parse or get converted to the internal representation. For
765 /// example if an invalid `head` was specified via `header("Foo",
766 /// "Bar\r\n")` the error will be returned when this function is called
767 /// rather than when `header` was called.
768 ///
769 /// # Examples
770 ///
771 /// ```
772 /// # use axol_http::*;
773 ///
774 /// let request = Request::builder()
775 /// .body(())
776 /// .unwrap();
777 /// ```
778 pub fn body(self, body: impl Into<Body>) -> Result<Request, RequestBuilderError> {
779 self.inner.map(move |mut head| {
780 head.body = body.into();
781 head
782 })
783 }
784
785 fn and_then<F>(self, func: F) -> Self
786 where
787 F: FnOnce(Request) -> Result<Request, RequestBuilderError>,
788 {
789 Builder {
790 inner: self.inner.and_then(func),
791 }
792 }
793}
794
795impl Default for Builder {
796 fn default() -> Builder {
797 Builder {
798 inner: Ok(Request::default()),
799 }
800 }
801}