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