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