//! HTTP response types. //! //! This module contains structs related to HTTP responses, notably the //! `Response` type itself as well as a builder to create responses. Typically //! you'll import the `http::Response` type rather than reaching into this //! module itself. //! //! # Examples //! //! Creating a `Response` to return //! //! ``` //! use http::{Request, Response, StatusCode}; //! //! fn respond_to(req: Request<()>) -> http::Result> { //! let mut builder = Response::builder() //! .header("Foo", "Bar") //! .status(StatusCode::OK); //! //! if req.headers().contains_key("Another-Header") { //! builder = builder.header("Another-Header", "Ack"); //! } //! //! builder.body(()) //! } //! ``` //! //! A simple 404 handler //! //! ``` //! use http::{Request, Response, StatusCode}; //! //! fn not_found(_req: Request<()>) -> http::Result> { //! Response::builder() //! .status(StatusCode::NOT_FOUND) //! .body(()) //! } //! ``` //! //! Or otherwise inspecting the result of a request: //! //! ```no_run //! use http::{Request, Response}; //! //! fn get(url: &str) -> http::Result> { //! // ... //! # panic!() //! } //! //! let response = get("https://www.rust-lang.org/").unwrap(); //! //! if !response.status().is_success() { //! panic!("failed to get a successful response status!"); //! } //! //! if let Some(date) = response.headers().get("Date") { //! // we've got a `Date` header! //! } //! //! let body = response.body(); //! // ... //! ``` use std::any::Any; use std::convert::TryFrom; use std::fmt; use crate::header::{HeaderMap, HeaderName, HeaderValue}; use crate::status::StatusCode; use crate::version::Version; use crate::{Extensions, Result}; /// Represents an HTTP response /// /// An HTTP response consists of a head and a potentially optional body. The body /// component is generic, enabling arbitrary types to represent the HTTP body. /// For example, the body could be `Vec`, a `Stream` of byte chunks, or a /// value that has been deserialized. /// /// Typically you'll work with responses on the client side as the result of /// sending a `Request` and on the server you'll be generating a `Response` to /// send back to the client. /// /// # Examples /// /// Creating a `Response` to return /// /// ``` /// use http::{Request, Response, StatusCode}; /// /// fn respond_to(req: Request<()>) -> http::Result> { /// let mut builder = Response::builder() /// .header("Foo", "Bar") /// .status(StatusCode::OK); /// /// if req.headers().contains_key("Another-Header") { /// builder = builder.header("Another-Header", "Ack"); /// } /// /// builder.body(()) /// } /// ``` /// /// A simple 404 handler /// /// ``` /// use http::{Request, Response, StatusCode}; /// /// fn not_found(_req: Request<()>) -> http::Result> { /// Response::builder() /// .status(StatusCode::NOT_FOUND) /// .body(()) /// } /// ``` /// /// Or otherwise inspecting the result of a request: /// /// ```no_run /// use http::{Request, Response}; /// /// fn get(url: &str) -> http::Result> { /// // ... /// # panic!() /// } /// /// let response = get("https://www.rust-lang.org/").unwrap(); /// /// if !response.status().is_success() { /// panic!("failed to get a successful response status!"); /// } /// /// if let Some(date) = response.headers().get("Date") { /// // we've got a `Date` header! /// } /// /// let body = response.body(); /// // ... /// ``` /// /// Deserialize a response of bytes via json: /// /// ``` /// # extern crate serde; /// # extern crate serde_json; /// # extern crate http; /// use http::Response; /// use serde::de; /// /// fn deserialize(res: Response>) -> serde_json::Result> /// where for<'de> T: de::Deserialize<'de>, /// { /// let (parts, body) = res.into_parts(); /// let body = serde_json::from_slice(&body)?; /// Ok(Response::from_parts(parts, body)) /// } /// # /// # fn main() {} /// ``` /// /// Or alternatively, serialize the body of a response to json /// /// ``` /// # extern crate serde; /// # extern crate serde_json; /// # extern crate http; /// use http::Response; /// use serde::ser; /// /// fn serialize(res: Response) -> serde_json::Result>> /// where T: ser::Serialize, /// { /// let (parts, body) = res.into_parts(); /// let body = serde_json::to_vec(&body)?; /// Ok(Response::from_parts(parts, body)) /// } /// # /// # fn main() {} /// ``` pub struct Response { head: Parts, body: T, } /// Component parts of an HTTP `Response` /// /// The HTTP response head consists of a status, version, and a set of /// header fields. pub struct Parts { /// The response's status pub status: StatusCode, /// The response's version pub version: Version, /// The response's headers pub headers: HeaderMap, /// The response's extensions pub extensions: Extensions, _priv: (), } /// An HTTP response builder /// /// This type can be used to construct an instance of `Response` through a /// builder-like pattern. #[derive(Debug)] pub struct Builder { inner: Result, } impl Response<()> { /// Creates a new builder-style object to manufacture a `Response` /// /// This method returns an instance of `Builder` which can be used to /// create a `Response`. /// /// # Examples /// /// ``` /// # use http::*; /// let response = Response::builder() /// .status(200) /// .header("X-Custom-Foo", "Bar") /// .body(()) /// .unwrap(); /// ``` #[inline] pub fn builder() -> Builder { Builder::new() } } impl Response { /// Creates a new blank `Response` with the body /// /// The component ports of this response will be set to their default, e.g. /// the ok status, no headers, etc. /// /// # Examples /// /// ``` /// # use http::*; /// let response = Response::new("hello world"); /// /// assert_eq!(response.status(), StatusCode::OK); /// assert_eq!(*response.body(), "hello world"); /// ``` #[inline] pub fn new(body: T) -> Response { Response { head: Parts::new(), body: body, } } /// Creates a new `Response` with the given head and body /// /// # Examples /// /// ``` /// # use http::*; /// let response = Response::new("hello world"); /// let (mut parts, body) = response.into_parts(); /// /// parts.status = StatusCode::BAD_REQUEST; /// let response = Response::from_parts(parts, body); /// /// assert_eq!(response.status(), StatusCode::BAD_REQUEST); /// assert_eq!(*response.body(), "hello world"); /// ``` #[inline] pub fn from_parts(parts: Parts, body: T) -> Response { Response { head: parts, body: body, } } /// Returns the `StatusCode`. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response<()> = Response::default(); /// assert_eq!(response.status(), StatusCode::OK); /// ``` #[inline] pub fn status(&self) -> StatusCode { self.head.status } /// Returns a mutable reference to the associated `StatusCode`. /// /// # Examples /// /// ``` /// # use http::*; /// let mut response: Response<()> = Response::default(); /// *response.status_mut() = StatusCode::CREATED; /// assert_eq!(response.status(), StatusCode::CREATED); /// ``` #[inline] pub fn status_mut(&mut self) -> &mut StatusCode { &mut self.head.status } /// Returns a reference to the associated version. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response<()> = Response::default(); /// assert_eq!(response.version(), Version::HTTP_11); /// ``` #[inline] pub fn version(&self) -> Version { self.head.version } /// Returns a mutable reference to the associated version. /// /// # Examples /// /// ``` /// # use http::*; /// let mut response: Response<()> = Response::default(); /// *response.version_mut() = Version::HTTP_2; /// assert_eq!(response.version(), Version::HTTP_2); /// ``` #[inline] pub fn version_mut(&mut self) -> &mut Version { &mut self.head.version } /// Returns a reference to the associated header field map. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response<()> = Response::default(); /// assert!(response.headers().is_empty()); /// ``` #[inline] pub fn headers(&self) -> &HeaderMap { &self.head.headers } /// Returns a mutable reference to the associated header field map. /// /// # Examples /// /// ``` /// # use http::*; /// # use http::header::*; /// let mut response: Response<()> = Response::default(); /// response.headers_mut().insert(HOST, HeaderValue::from_static("world")); /// assert!(!response.headers().is_empty()); /// ``` #[inline] pub fn headers_mut(&mut self) -> &mut HeaderMap { &mut self.head.headers } /// Returns a reference to the associated extensions. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response<()> = Response::default(); /// assert!(response.extensions().get::().is_none()); /// ``` #[inline] pub fn extensions(&self) -> &Extensions { &self.head.extensions } /// Returns a mutable reference to the associated extensions. /// /// # Examples /// /// ``` /// # use http::*; /// # use http::header::*; /// let mut response: Response<()> = Response::default(); /// response.extensions_mut().insert("hello"); /// assert_eq!(response.extensions().get(), Some(&"hello")); /// ``` #[inline] pub fn extensions_mut(&mut self) -> &mut Extensions { &mut self.head.extensions } /// Returns a reference to the associated HTTP body. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response = Response::default(); /// assert!(response.body().is_empty()); /// ``` #[inline] pub fn body(&self) -> &T { &self.body } /// Returns a mutable reference to the associated HTTP body. /// /// # Examples /// /// ``` /// # use http::*; /// let mut response: Response = Response::default(); /// response.body_mut().push_str("hello world"); /// assert!(!response.body().is_empty()); /// ``` #[inline] pub fn body_mut(&mut self) -> &mut T { &mut self.body } /// Consumes the response, returning just the body. /// /// # Examples /// /// ``` /// # use http::Response; /// let response = Response::new(10); /// let body = response.into_body(); /// assert_eq!(body, 10); /// ``` #[inline] pub fn into_body(self) -> T { self.body } /// Consumes the response returning the head and body parts. /// /// # Examples /// /// ``` /// # use http::*; /// let response: Response<()> = Response::default(); /// let (parts, body) = response.into_parts(); /// assert_eq!(parts.status, StatusCode::OK); /// ``` #[inline] pub fn into_parts(self) -> (Parts, T) { (self.head, self.body) } /// Consumes the response returning a new response with body mapped to the /// return type of the passed in function. /// /// # Examples /// /// ``` /// # use http::*; /// let response = Response::builder().body("some string").unwrap(); /// let mapped_response: Response<&[u8]> = response.map(|b| { /// assert_eq!(b, "some string"); /// b.as_bytes() /// }); /// assert_eq!(mapped_response.body(), &"some string".as_bytes()); /// ``` #[inline] pub fn map(self, f: F) -> Response where F: FnOnce(T) -> U, { Response { body: f(self.body), head: self.head, } } } impl Default for Response { #[inline] fn default() -> Response { Response::new(T::default()) } } impl fmt::Debug for Response { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Response") .field("status", &self.status()) .field("version", &self.version()) .field("headers", self.headers()) // omits Extensions because not useful .field("body", self.body()) .finish() } } impl Parts { /// Creates a new default instance of `Parts` fn new() -> Parts { Parts { status: StatusCode::default(), version: Version::default(), headers: HeaderMap::default(), extensions: Extensions::default(), _priv: (), } } } impl fmt::Debug for Parts { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Parts") .field("status", &self.status) .field("version", &self.version) .field("headers", &self.headers) // omits Extensions because not useful // omits _priv because not useful .finish() } } impl Builder { /// Creates a new default instance of `Builder` to construct either a /// `Head` or a `Response`. /// /// # Examples /// /// ``` /// # use http::*; /// /// let response = response::Builder::new() /// .status(200) /// .body(()) /// .unwrap(); /// ``` #[inline] pub fn new() -> Builder { Builder::default() } /// Set the HTTP status for this response. /// /// This function will configure the HTTP status code of the `Response` that /// will be returned from `Builder::build`. /// /// By default this is `200`. /// /// # Examples /// /// ``` /// # use http::*; /// /// let response = Response::builder() /// .status(200) /// .body(()) /// .unwrap(); /// ``` pub fn status(self, status: T) -> Builder where StatusCode: TryFrom, >::Error: Into, { self.and_then(move |mut head| { head.status = TryFrom::try_from(status).map_err(Into::into)?; Ok(head) }) } /// Set the HTTP version for this response. /// /// This function will configure the HTTP version of the `Response` that /// will be returned from `Builder::build`. /// /// By default this is HTTP/1.1 /// /// # Examples /// /// ``` /// # use http::*; /// /// let response = Response::builder() /// .version(Version::HTTP_2) /// .body(()) /// .unwrap(); /// ``` pub fn version(self, version: Version) -> Builder { self.and_then(move |mut head| { head.version = version; Ok(head) }) } /// Appends a header to this response builder. /// /// This function will append the provided key/value as a header to the /// internal `HeaderMap` being constructed. Essentially this is equivalent /// to calling `HeaderMap::append`. /// /// # Examples /// /// ``` /// # use http::*; /// # use http::header::HeaderValue; /// /// let response = Response::builder() /// .header("Content-Type", "text/html") /// .header("X-Custom-Foo", "bar") /// .header("content-length", 0) /// .body(()) /// .unwrap(); /// ``` pub fn header(self, key: K, value: V) -> Builder where HeaderName: TryFrom, >::Error: Into, HeaderValue: TryFrom, >::Error: Into, { self.and_then(move |mut head| { let name = >::try_from(key).map_err(Into::into)?; let value = >::try_from(value).map_err(Into::into)?; head.headers.append(name, value); Ok(head) }) } /// Get header on this response builder. /// /// When builder has error returns None. /// /// # Example /// /// ``` /// # use http::Response; /// # use http::header::HeaderValue; /// let res = Response::builder() /// .header("Accept", "text/html") /// .header("X-Custom-Foo", "bar"); /// let headers = res.headers_ref().unwrap(); /// assert_eq!( headers["Accept"], "text/html" ); /// assert_eq!( headers["X-Custom-Foo"], "bar" ); /// ``` pub fn headers_ref(&self) -> Option<&HeaderMap> { self.inner.as_ref().ok().map(|h| &h.headers) } /// Get header on this response builder. /// when builder has error returns None /// /// # Example /// /// ``` /// # use http::*; /// # use http::header::HeaderValue; /// # use http::response::Builder; /// let mut res = Response::builder(); /// { /// let headers = res.headers_mut().unwrap(); /// headers.insert("Accept", HeaderValue::from_static("text/html")); /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar")); /// } /// let headers = res.headers_ref().unwrap(); /// assert_eq!( headers["Accept"], "text/html" ); /// assert_eq!( headers["X-Custom-Foo"], "bar" ); /// ``` pub fn headers_mut(&mut self) -> Option<&mut HeaderMap> { self.inner.as_mut().ok().map(|h| &mut h.headers) } /// Adds an extension to this builder /// /// # Examples /// /// ``` /// # use http::*; /// /// let response = Response::builder() /// .extension("My Extension") /// .body(()) /// .unwrap(); /// /// assert_eq!(response.extensions().get::<&'static str>(), /// Some(&"My Extension")); /// ``` pub fn extension(self, extension: T) -> Builder where T: Any + Send + Sync + 'static, { self.and_then(move |mut head| { head.extensions.insert(extension); Ok(head) }) } /// Get a reference to the extensions for this response builder. /// /// If the builder has an error, this returns `None`. /// /// # Example /// /// ``` /// # use http::Response; /// let res = Response::builder().extension("My Extension").extension(5u32); /// let extensions = res.extensions_ref().unwrap(); /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension")); /// assert_eq!(extensions.get::(), Some(&5u32)); /// ``` pub fn extensions_ref(&self) -> Option<&Extensions> { self.inner.as_ref().ok().map(|h| &h.extensions) } /// Get a mutable reference to the extensions for this response builder. /// /// If the builder has an error, this returns `None`. /// /// # Example /// /// ``` /// # use http::Response; /// let mut res = Response::builder().extension("My Extension"); /// let mut extensions = res.extensions_mut().unwrap(); /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension")); /// extensions.insert(5u32); /// assert_eq!(extensions.get::(), Some(&5u32)); /// ``` pub fn extensions_mut(&mut self) -> Option<&mut Extensions> { self.inner.as_mut().ok().map(|h| &mut h.extensions) } /// "Consumes" this builder, using the provided `body` to return a /// constructed `Response`. /// /// # Errors /// /// This function may return an error if any previously configured argument /// failed to parse or get converted to the internal representation. For /// example if an invalid `head` was specified via `header("Foo", /// "Bar\r\n")` the error will be returned when this function is called /// rather than when `header` was called. /// /// # Examples /// /// ``` /// # use http::*; /// /// let response = Response::builder() /// .body(()) /// .unwrap(); /// ``` pub fn body(self, body: T) -> Result> { self.inner.map(move |head| { Response { head, body, } }) } // private fn and_then(self, func: F) -> Self where F: FnOnce(Parts) -> Result { Builder { inner: self.inner.and_then(func), } } } impl Default for Builder { #[inline] fn default() -> Builder { Builder { inner: Ok(Parts::new()), } } } #[cfg(test)] mod tests { use super::*; #[test] fn it_can_map_a_body_from_one_type_to_another() { let response = Response::builder().body("some string").unwrap(); let mapped_response = response.map(|s| { assert_eq!(s, "some string"); 123u32 }); assert_eq!(mapped_response.body(), &123u32); } }