rama_http_types/response.rs
1use std::borrow::Cow;
2use std::convert::TryInto;
3use std::fmt::{self, Display};
4
5use crate::header::{HeaderMap, HeaderName, HeaderValue};
6use crate::proto::h1::ext::ReasonPhrase;
7use crate::status::StatusCode;
8use crate::version::Version;
9use crate::{Body, Result};
10use rama_core::extensions::{Extension, Extensions, ExtensionsRef};
11use rama_utils::macros::generate_set_and_with;
12
13/// Represents an HTTP response
14///
15/// An HTTP response consists of a head and a potentially optional body. The body
16/// component is generic, enabling arbitrary types to represent the HTTP body.
17/// For example, the body could be `Vec<u8>`, a `Stream` of byte chunks, or a
18/// value that has been deserialized.
19///
20/// Typically you'll work with responses on the client side as the result of
21/// sending a `Request` and on the server you'll be generating a `Response` to
22/// send back to the client.
23///
24/// # Examples
25///
26/// Creating a `Response` to return
27///
28/// ```
29/// use rama_http_types::{Request, Response, StatusCode};
30///
31/// fn respond_to(req: Request<()>) -> rama_http_types::Result<Response<()>> {
32/// let mut builder = Response::builder()
33/// .header("Foo", "Bar")
34/// .status(StatusCode::OK);
35///
36/// if req.headers().contains_key("Another-Header") {
37/// builder = builder.header("Another-Header", "Ack");
38/// }
39///
40/// builder.body(())
41/// }
42/// ```
43///
44/// A simple 404 handler
45///
46/// ```
47/// use rama_http_types::{Request, Response, StatusCode};
48///
49/// fn not_found(_req: Request<()>) -> rama_http_types::Result<Response<()>> {
50/// Response::builder()
51/// .status(StatusCode::NOT_FOUND)
52/// .body(())
53/// }
54/// ```
55///
56/// Or otherwise inspecting the result of a request:
57///
58/// ```no_run
59/// use rama_http_types::{Request, Response};
60///
61/// fn get(url: &str) -> rama_http_types::Result<Response<()>> {
62/// // ...
63/// # panic!()
64/// }
65///
66/// let response = get("https://www.rust-lang.org/").unwrap();
67///
68/// if !response.status().is_success() {
69/// panic!("failed to get a successful response status!");
70/// }
71///
72/// if let Some(date) = response.headers().get("Date") {
73/// // we've got a `Date` header!
74/// }
75///
76/// let body = response.body();
77/// // ...
78/// ```
79///
80/// Deserialize a response of bytes via json:
81///
82/// ```
83/// use rama_http_types::Response;
84/// use serde::de;
85///
86/// fn deserialize<T>(res: Response<Vec<u8>>) -> serde_json::Result<Response<T>>
87/// where for<'de> T: de::Deserialize<'de>,
88/// {
89/// let (parts, body) = res.into_parts();
90/// let body = serde_json::from_slice(&body)?;
91/// Ok(Response::from_parts(parts, body))
92/// }
93/// #
94/// # fn main() {}
95/// ```
96///
97/// Or alternatively, serialize the body of a response to json
98///
99/// ```
100/// use rama_http_types::Response;
101/// use serde::ser;
102///
103/// fn serialize<T>(res: Response<T>) -> serde_json::Result<Response<Vec<u8>>>
104/// where T: ser::Serialize,
105/// {
106/// let (parts, body) = res.into_parts();
107/// let body = serde_json::to_vec(&body)?;
108/// Ok(Response::from_parts(parts, body))
109/// }
110/// #
111/// # fn main() {}
112/// ```
113#[derive(Clone)]
114pub struct Response<T = Body> {
115 head: Parts,
116 body: T,
117}
118
119/// Component parts of an HTTP `Response`
120///
121/// The HTTP response head consists of a status, version, and a set of
122/// header fields.
123#[non_exhaustive]
124#[derive(Clone)]
125pub struct Parts {
126 /// The response's status
127 pub status: StatusCode,
128
129 /// The response's version
130 pub version: Version,
131
132 /// The response's headers
133 pub headers: HeaderMap<HeaderValue>,
134
135 /// The response's extensions
136 pub extensions: Extensions,
137}
138
139impl ExtensionsRef for Parts {
140 fn extensions(&self) -> &Extensions {
141 &self.extensions
142 }
143}
144
145/// An HTTP response builder
146///
147/// This type can be used to construct an instance of `Response` through a
148/// builder-like pattern.
149#[derive(Debug)]
150#[must_use]
151pub struct Builder {
152 inner: Result<Parts>,
153}
154
155impl Response<()> {
156 /// Creates a new builder-style object to manufacture a `Response`
157 ///
158 /// This method returns an instance of `Builder` which can be used to
159 /// create a `Response`.
160 ///
161 /// # Examples
162 ///
163 /// ```
164 /// # use rama_http_types::*;
165 /// let response = Response::builder()
166 /// .status(200)
167 /// .header("X-Custom-Foo", "Bar")
168 /// .body(())
169 /// .unwrap();
170 /// ```
171 #[inline]
172 pub fn builder() -> Builder {
173 Builder::new()
174 }
175
176 #[inline]
177 /// Same as [`Response::builder`] but with the given [`Extensions`] to start from.
178 pub fn builder_with_extensions(ext: Extensions) -> Builder {
179 Builder::new_with_extensions(ext)
180 }
181}
182
183impl<T> Response<T> {
184 /// Creates a new blank `Response` with the body
185 ///
186 /// The component parts of this response will be set to their default, e.g.
187 /// the ok status, no headers, etc.
188 ///
189 /// # Examples
190 ///
191 /// ```
192 /// # use rama_http_types::*;
193 /// let response = Response::new("hello world");
194 ///
195 /// assert_eq!(response.status(), StatusCode::OK);
196 /// assert_eq!(*response.body(), "hello world");
197 /// ```
198 #[inline]
199 pub fn new(body: T) -> Self {
200 Self {
201 head: Parts::new(),
202 body,
203 }
204 }
205
206 /// Creates a new `Response` with the given head and body
207 ///
208 /// # Examples
209 ///
210 /// ```
211 /// # use rama_http_types::*;
212 /// let response = Response::new("hello world");
213 /// let (mut parts, body) = response.into_parts();
214 ///
215 /// parts.status = StatusCode::BAD_REQUEST;
216 /// let response = Response::from_parts(parts, body);
217 ///
218 /// assert_eq!(response.status(), StatusCode::BAD_REQUEST);
219 /// assert_eq!(*response.body(), "hello world");
220 /// ```
221 #[inline]
222 pub fn from_parts(parts: Parts, body: T) -> Self {
223 Self { head: parts, body }
224 }
225
226 /// Returns the `StatusCode`.
227 ///
228 /// # Examples
229 ///
230 /// ```
231 /// # use rama_http_types::*;
232 /// let response: Response<()> = Response::default();
233 /// assert_eq!(response.status(), StatusCode::OK);
234 /// ```
235 #[inline]
236 pub fn status(&self) -> StatusCode {
237 self.head.status
238 }
239
240 /// Returns a mutable reference to the associated `StatusCode`.
241 ///
242 /// # Examples
243 ///
244 /// ```
245 /// # use rama_http_types::*;
246 /// let mut response: Response<()> = Response::default();
247 /// *response.status_mut() = StatusCode::CREATED;
248 /// assert_eq!(response.status(), StatusCode::CREATED);
249 /// ```
250 #[inline]
251 pub fn status_mut(&mut self) -> &mut StatusCode {
252 &mut self.head.status
253 }
254
255 /// Turn a response into an error if the server returned an error.
256 ///
257 /// # Example
258 ///
259 /// ```
260 /// # use rama_http_types::Response;
261 /// fn on_response(res: Response) {
262 /// match res.error_for_status() {
263 /// Ok(_res) => (),
264 /// Err(err) => {
265 /// // asserting a 400 as an example
266 /// // it could be any status between 400...599
267 /// assert_eq!(
268 /// err.status(),
269 /// rama_http_types::StatusCode::BAD_REQUEST,
270 /// );
271 /// }
272 /// }
273 /// }
274 /// # fn main() {}
275 /// ```
276 pub fn error_for_status(self) -> std::result::Result<Self, StatusCodeError> {
277 let status = self.status();
278
279 if status.is_client_error() || status.is_server_error() {
280 Err(StatusCodeError {
281 status,
282 reason: match self.extensions().get_ref::<ReasonPhrase>() {
283 Some(reason) => Some(
284 String::from_utf8_lossy(reason.as_bytes())
285 .into_owned()
286 .into(),
287 ),
288 None => status.canonical_reason().map(Into::into),
289 },
290 })
291 } else {
292 Ok(self)
293 }
294 }
295
296 /// Turn a reference to a response into an error if the server returned an error.
297 ///
298 /// # Example
299 ///
300 /// ```
301 /// # use rama_http_types::Response;
302 /// fn on_response(res: &Response) {
303 /// match res.error_for_status_ref() {
304 /// Ok(_res) => (),
305 /// Err(err) => {
306 /// // asserting a 400 as an example
307 /// // it could be any status between 400...599
308 /// assert_eq!(
309 /// err.status(),
310 /// rama_http_types::StatusCode::BAD_REQUEST
311 /// );
312 /// }
313 /// }
314 /// }
315 /// # fn main() {}
316 /// ```
317 pub fn error_for_status_ref(&self) -> std::result::Result<&Self, StatusCodeError> {
318 let status = self.status();
319
320 if status.is_client_error() || status.is_server_error() {
321 Err(StatusCodeError {
322 status,
323 reason: match self.extensions().get_ref::<ReasonPhrase>() {
324 Some(reason) => Some(
325 String::from_utf8_lossy(reason.as_bytes())
326 .into_owned()
327 .into(),
328 ),
329 None => status.canonical_reason().map(Into::into),
330 },
331 })
332 } else {
333 Ok(self)
334 }
335 }
336
337 /// Returns a reference to the associated version.
338 ///
339 /// # Examples
340 ///
341 /// ```
342 /// # use rama_http_types::*;
343 /// let response: Response<()> = Response::default();
344 /// assert_eq!(response.version(), Version::HTTP_11);
345 /// ```
346 #[inline]
347 pub fn version(&self) -> Version {
348 self.head.version
349 }
350
351 /// Returns a mutable reference to the associated version.
352 ///
353 /// # Examples
354 ///
355 /// ```
356 /// # use rama_http_types::*;
357 /// let mut response: Response<()> = Response::default();
358 /// *response.version_mut() = Version::HTTP_2;
359 /// assert_eq!(response.version(), Version::HTTP_2);
360 /// ```
361 #[inline]
362 pub fn version_mut(&mut self) -> &mut Version {
363 &mut self.head.version
364 }
365
366 /// Returns a reference to the associated header field map.
367 ///
368 /// # Examples
369 ///
370 /// ```
371 /// # use rama_http_types::*;
372 /// let response: Response<()> = Response::default();
373 /// assert!(response.headers().is_empty());
374 /// ```
375 #[inline]
376 pub fn headers(&self) -> &HeaderMap<HeaderValue> {
377 &self.head.headers
378 }
379
380 /// Returns a mutable reference to the associated header field map.
381 ///
382 /// # Examples
383 ///
384 /// ```
385 /// # use rama_http_types::*;
386 /// # use rama_http_types::header::*;
387 /// let mut response: Response<()> = Response::default();
388 /// response.headers_mut().insert(HOST, HeaderValue::from_static("world"));
389 /// assert!(!response.headers().is_empty());
390 /// ```
391 #[inline]
392 pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
393 &mut self.head.headers
394 }
395
396 /// Returned a cloned of the associated HTTP header.
397 #[inline]
398 pub fn clone_parts(&self) -> Parts {
399 self.head.clone()
400 }
401
402 /// Returns a reference to the associated HTTP body.
403 ///
404 /// # Examples
405 ///
406 /// ```
407 /// # use rama_http_types::*;
408 /// let response: Response<String> = Response::default();
409 /// assert!(response.body().is_empty());
410 /// ```
411 #[inline]
412 pub fn body(&self) -> &T {
413 &self.body
414 }
415
416 /// Returns a mutable reference to the associated HTTP body.
417 ///
418 /// # Examples
419 ///
420 /// ```
421 /// # use rama_http_types::*;
422 /// let mut response: Response<String> = Response::default();
423 /// response.body_mut().push_str("hello world");
424 /// assert!(!response.body().is_empty());
425 /// ```
426 #[inline]
427 pub fn body_mut(&mut self) -> &mut T {
428 &mut self.body
429 }
430
431 /// Consumes the response, returning just the body.
432 ///
433 /// # Examples
434 ///
435 /// ```
436 /// # use rama_http_types::Response;
437 /// let response = Response::new(10);
438 /// let body = response.into_body();
439 /// assert_eq!(body, 10);
440 /// ```
441 #[inline]
442 pub fn into_body(self) -> T {
443 self.body
444 }
445
446 /// Consumes the response returning the head and body parts.
447 ///
448 /// # Examples
449 ///
450 /// ```
451 /// # use rama_http_types::*;
452 /// let response: Response<()> = Response::default();
453 /// let (parts, body) = response.into_parts();
454 /// assert_eq!(parts.status, StatusCode::OK);
455 /// ```
456 #[inline]
457 pub fn into_parts(self) -> (Parts, T) {
458 (self.head, self.body)
459 }
460
461 /// Consumes the response returning a new response with body mapped to the
462 /// return type of the passed in function.
463 ///
464 /// # Examples
465 ///
466 /// ```
467 /// # use rama_http_types::*;
468 /// let response = Response::builder().body("some string").unwrap();
469 /// let mapped_response: Response<&[u8]> = response.map(|b| {
470 /// assert_eq!(b, "some string");
471 /// b.as_bytes()
472 /// });
473 /// assert_eq!(mapped_response.body(), &"some string".as_bytes());
474 /// ```
475 #[inline]
476 pub fn map<F, U>(self, f: F) -> Response<U>
477 where
478 F: FnOnce(T) -> U,
479 {
480 Response {
481 body: f(self.body),
482 head: self.head,
483 }
484 }
485
486 generate_set_and_with! {
487 pub fn extensions(mut self, extensions: Extensions) -> Self {
488 self.head.extensions = extensions;
489 self
490 }
491 }
492}
493
494impl<T: Default> Default for Response<T> {
495 #[inline]
496 fn default() -> Self {
497 Self::new(T::default())
498 }
499}
500
501impl<T: fmt::Debug> fmt::Debug for Response<T> {
502 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
503 f.debug_struct("Response")
504 .field("status", &self.status())
505 .field("version", &self.version())
506 .field("headers", self.headers())
507 // omits Extensions because not useful
508 .field("body", self.body())
509 .finish()
510 }
511}
512
513impl<T> ExtensionsRef for Response<T> {
514 fn extensions(&self) -> &Extensions {
515 &self.head.extensions
516 }
517}
518
519#[derive(Debug)]
520/// Error generated by a client or server status code.
521pub struct StatusCodeError {
522 status: StatusCode,
523 reason: Option<Cow<'static, str>>,
524}
525
526impl StatusCodeError {
527 pub fn status(&self) -> StatusCode {
528 self.status
529 }
530
531 pub fn reason(&self) -> Option<&str> {
532 self.reason.as_deref()
533 }
534}
535
536impl Display for StatusCodeError {
537 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
538 if self.status.is_client_error() {
539 write!(
540 f,
541 "http client error: status={}; reason: '{}'",
542 self.status,
543 self.reason.as_deref().unwrap_or_default(),
544 )
545 } else if self.status.is_server_error() {
546 write!(
547 f,
548 "http server error: status={}; reason: '{}'",
549 self.status,
550 self.reason.as_deref().unwrap_or_default(),
551 )
552 } else {
553 write!(
554 f,
555 "http error: status={}; reason: '{}'",
556 self.status,
557 self.reason.as_deref().unwrap_or_default(),
558 )
559 }
560 }
561}
562
563impl std::error::Error for StatusCodeError {}
564
565impl Parts {
566 /// Creates a new default instance of `Parts`
567 fn new() -> Self {
568 Self {
569 status: StatusCode::default(),
570 version: Version::default(),
571 headers: HeaderMap::default(),
572 extensions: Extensions::default(),
573 }
574 }
575}
576
577impl fmt::Debug for Parts {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 f.debug_struct("Parts")
580 .field("status", &self.status)
581 .field("version", &self.version)
582 .field("headers", &self.headers)
583 // omits Extensions because not useful
584 // omits _priv because not useful
585 .finish()
586 }
587}
588
589impl Builder {
590 /// Creates a new default instance of `Builder` to construct either a
591 /// `Head` or a `Response`.
592 ///
593 /// # Examples
594 ///
595 /// ```
596 /// # use rama_http_types::*;
597 ///
598 /// let response = response::Builder::new()
599 /// .status(200)
600 /// .body(())
601 /// .unwrap();
602 /// ```
603 #[inline]
604 pub fn new() -> Self {
605 Self::default()
606 }
607
608 #[inline]
609 /// Same as [`Self::new`] but with the given [`Extensions`] to start from.
610 pub fn new_with_extensions(ext: Extensions) -> Self {
611 Self {
612 inner: Ok(Parts {
613 status: StatusCode::default(),
614 version: Version::default(),
615 headers: HeaderMap::default(),
616 extensions: ext,
617 }),
618 }
619 }
620
621 /// Set the HTTP status for this response.
622 ///
623 /// By default this is `200`.
624 ///
625 /// # Examples
626 ///
627 /// ```
628 /// # use rama_http_types::*;
629 ///
630 /// let response = Response::builder()
631 /// .status(200)
632 /// .body(())
633 /// .unwrap();
634 /// ```
635 pub fn status<T>(self, status: T) -> Self
636 where
637 T: TryInto<StatusCode>,
638 <T as TryInto<StatusCode>>::Error: Into<crate::Error>,
639 {
640 self.and_then(move |mut head| {
641 head.status = status.try_into().map_err(Into::into)?;
642 Ok(head)
643 })
644 }
645
646 /// Set the HTTP version for this response.
647 ///
648 /// By default this is HTTP/1.1
649 ///
650 /// # Examples
651 ///
652 /// ```
653 /// # use rama_http_types::*;
654 ///
655 /// let response = Response::builder()
656 /// .version(Version::HTTP_2)
657 /// .body(())
658 /// .unwrap();
659 /// ```
660 pub fn version(self, version: Version) -> Self {
661 self.and_then(move |mut head| {
662 head.version = version;
663 Ok(head)
664 })
665 }
666
667 /// Appends a header to this response builder.
668 ///
669 /// This function will append the provided key/value as a header to the
670 /// internal `HeaderMap` being constructed. Essentially this is equivalent
671 /// to calling `HeaderMap::append`.
672 ///
673 /// # Examples
674 ///
675 /// ```
676 /// # use rama_http_types::*;
677 /// # use rama_http_types::header::HeaderValue;
678 ///
679 /// let response = Response::builder()
680 /// .header("Content-Type", "text/html")
681 /// .header("X-Custom-Foo", "bar")
682 /// .header("content-length", 0)
683 /// .body(())
684 /// .unwrap();
685 /// ```
686 pub fn header<K, V>(self, key: K, value: V) -> Self
687 where
688 K: TryInto<HeaderName>,
689 <K as TryInto<HeaderName>>::Error: Into<crate::Error>,
690 V: TryInto<HeaderValue>,
691 <V as TryInto<HeaderValue>>::Error: Into<crate::Error>,
692 {
693 self.and_then(move |mut head| {
694 let name = key.try_into().map_err(Into::into)?;
695 let value = value.try_into().map_err(Into::into)?;
696 head.headers.try_append(name, value)?;
697 Ok(head)
698 })
699 }
700
701 /// Get header on this response builder.
702 ///
703 /// When builder has error returns None.
704 ///
705 /// # Example
706 ///
707 /// ```
708 /// # use rama_http_types::Response;
709 /// # use rama_http_types::header::HeaderValue;
710 /// let res = Response::builder()
711 /// .header("Accept", "text/html")
712 /// .header("X-Custom-Foo", "bar");
713 /// let headers = res.headers_ref().unwrap();
714 /// assert_eq!( headers["Accept"], "text/html" );
715 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
716 /// ```
717 #[must_use]
718 pub fn headers_ref(&self) -> Option<&HeaderMap<HeaderValue>> {
719 self.inner.as_ref().ok().map(|h| &h.headers)
720 }
721
722 /// Get header on this response builder.
723 /// when builder has error returns None
724 ///
725 /// # Example
726 ///
727 /// ```
728 /// # use rama_http_types::*;
729 /// # use rama_http_types::header::HeaderValue;
730 /// # use rama_http_types::response::Builder;
731 /// let mut res = Response::builder();
732 /// {
733 /// let headers = res.headers_mut().unwrap();
734 /// headers.insert("Accept", HeaderValue::from_static("text/html"));
735 /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar"));
736 /// }
737 /// let headers = res.headers_ref().unwrap();
738 /// assert_eq!( headers["Accept"], "text/html" );
739 /// assert_eq!( headers["X-Custom-Foo"], "bar" );
740 /// ```
741 pub fn headers_mut(&mut self) -> Option<&mut HeaderMap<HeaderValue>> {
742 self.inner.as_mut().ok().map(|h| &mut h.headers)
743 }
744
745 /// Adds an extension to this builder
746 ///
747 /// # Examples
748 ///
749 /// ```
750 /// # use rama_http_types::Response;
751 /// # use rama_core::extensions::{Extension, ExtensionsRef as _};
752 ///
753 /// #[derive(Debug, Clone, PartialEq)]
754 /// struct MyExtension(&'static str);
755 /// impl Extension for MyExtension {}
756 ///
757 /// let response = Response::builder()
758 /// .extension(MyExtension("My Extension"))
759 /// .body(())
760 /// .unwrap();
761 ///
762 /// assert_eq!(response.extensions().get_ref::<MyExtension>(),
763 /// Some(&MyExtension("My Extension")));
764 /// ```
765 pub fn extension<T>(self, extension: T) -> Self
766 where
767 T: Extension,
768 {
769 self.and_then(move |head| {
770 head.extensions.insert(extension);
771 Ok(head)
772 })
773 }
774
775 /// Get a reference to the extensions for this response builder.
776 ///
777 /// If the builder has an error, this returns `None`.
778 ///
779 /// # Example
780 ///
781 /// ```
782 /// # use rama_http_types::Response;
783 /// # use rama_core::extensions::Extension;
784 /// #[derive(Debug, Clone, PartialEq)]
785 /// struct MyExtension(&'static str);
786 /// impl Extension for MyExtension {}
787 ///
788 /// #[derive(Debug, Clone, PartialEq)]
789 /// struct MyCount(u32);
790 /// impl Extension for MyCount {}
791 ///
792 /// let res = Response::builder().extension(MyExtension("My Extension")).extension(MyCount(5));
793 /// let extensions = res.extensions().unwrap();
794 /// assert_eq!(extensions.get_ref::<MyExtension>(), Some(&MyExtension("My Extension")));
795 /// assert_eq!(extensions.get_ref::<MyCount>(), Some(&MyCount(5)));
796 /// ```
797 #[must_use]
798 pub fn extensions(&self) -> Option<&Extensions> {
799 self.inner.as_ref().ok().map(|h| &h.extensions)
800 }
801
802 /// "Consumes" this builder, using the provided `body` to return a
803 /// constructed `Response`.
804 ///
805 /// # Errors
806 ///
807 /// This function may return an error if any previously configured argument
808 /// failed to parse or get converted to the internal representation. For
809 /// example if an invalid `head` was specified via `header("Foo",
810 /// "Bar\r\n")` the error will be returned when this function is called
811 /// rather than when `header` was called.
812 ///
813 /// # Examples
814 ///
815 /// ```
816 /// # use rama_http_types::*;
817 ///
818 /// let response = Response::builder()
819 /// .body(())
820 /// .unwrap();
821 /// ```
822 pub fn body<T>(self, body: T) -> Result<Response<T>> {
823 self.inner.map(move |head| Response { head, body })
824 }
825
826 // private
827
828 fn and_then<F>(self, func: F) -> Self
829 where
830 F: FnOnce(Parts) -> Result<Parts>,
831 {
832 Self {
833 inner: self.inner.and_then(func),
834 }
835 }
836}
837
838impl Default for Builder {
839 #[inline]
840 fn default() -> Self {
841 Self {
842 inner: Ok(Parts::new()),
843 }
844 }
845}
846
847#[cfg(test)]
848mod tests {
849 use super::*;
850
851 #[test]
852 fn it_can_map_a_body_from_one_type_to_another() {
853 let response = Response::builder().body("some string").unwrap();
854 let mapped_response = response.map(|s| {
855 assert_eq!(s, "some string");
856 123u32
857 });
858 assert_eq!(mapped_response.body(), &123u32);
859 }
860}