| //! HTTP request types. |
| //! |
| //! This module contains structs related to HTTP requests, notably the |
| //! `Request` type itself as well as a builder to create requests. Typically |
| //! you'll import the `http::Request` type rather than reaching into this |
| //! module itself. |
| //! |
| //! # Examples |
| //! |
| //! Creating a `Request` to send |
| //! |
| //! ```no_run |
| //! use http::{Request, Response}; |
| //! |
| //! let mut request = Request::builder() |
| //! .uri("https://www.rust-lang.org/") |
| //! .header("User-Agent", "my-awesome-agent/1.0"); |
| //! |
| //! if needs_awesome_header() { |
| //! request = request.header("Awesome", "yes"); |
| //! } |
| //! |
| //! let response = send(request.body(()).unwrap()); |
| //! |
| //! # fn needs_awesome_header() -> bool { |
| //! # true |
| //! # } |
| //! # |
| //! fn send(req: Request<()>) -> Response<()> { |
| //! // ... |
| //! # panic!() |
| //! } |
| //! ``` |
| //! |
| //! Inspecting a request to see what was sent. |
| //! |
| //! ``` |
| //! use http::{Request, Response, StatusCode}; |
| //! |
| //! fn respond_to(req: Request<()>) -> http::Result<Response<()>> { |
| //! if req.uri() != "/awesome-url" { |
| //! return Response::builder() |
| //! .status(StatusCode::NOT_FOUND) |
| //! .body(()) |
| //! } |
| //! |
| //! let has_awesome_header = req.headers().contains_key("Awesome"); |
| //! let body = req.body(); |
| //! |
| //! // ... |
| //! # panic!() |
| //! } |
| //! ``` |
| |
| use std::any::Any; |
| use std::convert::{TryFrom}; |
| use std::fmt; |
| |
| use crate::header::{HeaderMap, HeaderName, HeaderValue}; |
| use crate::method::Method; |
| use crate::version::Version; |
| use crate::{Extensions, Result, Uri}; |
| |
| /// Represents an HTTP request. |
| /// |
| /// An HTTP request 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<u8>`, a `Stream` of byte chunks, or a |
| /// value that has been deserialized. |
| /// |
| /// # Examples |
| /// |
| /// Creating a `Request` to send |
| /// |
| /// ```no_run |
| /// use http::{Request, Response}; |
| /// |
| /// let mut request = Request::builder() |
| /// .uri("https://www.rust-lang.org/") |
| /// .header("User-Agent", "my-awesome-agent/1.0"); |
| /// |
| /// if needs_awesome_header() { |
| /// request = request.header("Awesome", "yes"); |
| /// } |
| /// |
| /// let response = send(request.body(()).unwrap()); |
| /// |
| /// # fn needs_awesome_header() -> bool { |
| /// # true |
| /// # } |
| /// # |
| /// fn send(req: Request<()>) -> Response<()> { |
| /// // ... |
| /// # panic!() |
| /// } |
| /// ``` |
| /// |
| /// Inspecting a request to see what was sent. |
| /// |
| /// ``` |
| /// use http::{Request, Response, StatusCode}; |
| /// |
| /// fn respond_to(req: Request<()>) -> http::Result<Response<()>> { |
| /// if req.uri() != "/awesome-url" { |
| /// return Response::builder() |
| /// .status(StatusCode::NOT_FOUND) |
| /// .body(()) |
| /// } |
| /// |
| /// let has_awesome_header = req.headers().contains_key("Awesome"); |
| /// let body = req.body(); |
| /// |
| /// // ... |
| /// # panic!() |
| /// } |
| /// ``` |
| /// |
| /// Deserialize a request of bytes via json: |
| /// |
| /// ``` |
| /// # extern crate serde; |
| /// # extern crate serde_json; |
| /// # extern crate http; |
| /// use http::Request; |
| /// use serde::de; |
| /// |
| /// fn deserialize<T>(req: Request<Vec<u8>>) -> serde_json::Result<Request<T>> |
| /// where for<'de> T: de::Deserialize<'de>, |
| /// { |
| /// let (parts, body) = req.into_parts(); |
| /// let body = serde_json::from_slice(&body)?; |
| /// Ok(Request::from_parts(parts, body)) |
| /// } |
| /// # |
| /// # fn main() {} |
| /// ``` |
| /// |
| /// Or alternatively, serialize the body of a request to json |
| /// |
| /// ``` |
| /// # extern crate serde; |
| /// # extern crate serde_json; |
| /// # extern crate http; |
| /// use http::Request; |
| /// use serde::ser; |
| /// |
| /// fn serialize<T>(req: Request<T>) -> serde_json::Result<Request<Vec<u8>>> |
| /// where T: ser::Serialize, |
| /// { |
| /// let (parts, body) = req.into_parts(); |
| /// let body = serde_json::to_vec(&body)?; |
| /// Ok(Request::from_parts(parts, body)) |
| /// } |
| /// # |
| /// # fn main() {} |
| /// ``` |
| pub struct Request<T> { |
| head: Parts, |
| body: T, |
| } |
| |
| /// Component parts of an HTTP `Request` |
| /// |
| /// The HTTP request head consists of a method, uri, version, and a set of |
| /// header fields. |
| pub struct Parts { |
| /// The request's method |
| pub method: Method, |
| |
| /// The request's URI |
| pub uri: Uri, |
| |
| /// The request's version |
| pub version: Version, |
| |
| /// The request's headers |
| pub headers: HeaderMap<HeaderValue>, |
| |
| /// The request's extensions |
| pub extensions: Extensions, |
| |
| _priv: (), |
| } |
| |
| /// An HTTP request builder |
| /// |
| /// This type can be used to construct an instance or `Request` |
| /// through a builder-like pattern. |
| #[derive(Debug)] |
| pub struct Builder { |
| inner: Result<Parts>, |
| } |
| |
| impl Request<()> { |
| /// Creates a new builder-style object to manufacture a `Request` |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request = Request::builder() |
| /// .method("GET") |
| /// .uri("https://www.rust-lang.org/") |
| /// .header("X-Custom-Foo", "Bar") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| #[inline] |
| pub fn builder() -> Builder { |
| Builder::new() |
| } |
| |
| /// Creates a new `Builder` initialized with a GET method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::get("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn get<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::GET).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a PUT method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::put("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn put<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::PUT).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a POST method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::post("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn post<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::POST).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a DELETE method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::delete("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn delete<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::DELETE).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with an OPTIONS method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::options("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// # assert_eq!(*request.method(), Method::OPTIONS); |
| /// ``` |
| pub fn options<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::OPTIONS).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a HEAD method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::head("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn head<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::HEAD).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a CONNECT method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::connect("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn connect<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| |
| { |
| Builder::new().method(Method::CONNECT).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a PATCH method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::patch("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn patch<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| { |
| Builder::new().method(Method::PATCH).uri(uri) |
| } |
| |
| /// Creates a new `Builder` initialized with a TRACE method and the given URI. |
| /// |
| /// This method returns an instance of `Builder` which can be used to |
| /// create a `Request`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let request = Request::trace("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn trace<T>(uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| { |
| Builder::new().method(Method::TRACE).uri(uri) |
| } |
| } |
| |
| impl<T> Request<T> { |
| /// Creates a new blank `Request` with the body |
| /// |
| /// The component parts of this request will be set to their default, e.g. |
| /// the GET method, no headers, etc. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request = Request::new("hello world"); |
| /// |
| /// assert_eq!(*request.method(), Method::GET); |
| /// assert_eq!(*request.body(), "hello world"); |
| /// ``` |
| #[inline] |
| pub fn new(body: T) -> Request<T> { |
| Request { |
| head: Parts::new(), |
| body: body, |
| } |
| } |
| |
| /// Creates a new `Request` with the given components parts and body. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request = Request::new("hello world"); |
| /// let (mut parts, body) = request.into_parts(); |
| /// parts.method = Method::POST; |
| /// |
| /// let request = Request::from_parts(parts, body); |
| /// ``` |
| #[inline] |
| pub fn from_parts(parts: Parts, body: T) -> Request<T> { |
| Request { |
| head: parts, |
| body: body, |
| } |
| } |
| |
| /// Returns a reference to the associated HTTP method. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request: Request<()> = Request::default(); |
| /// assert_eq!(*request.method(), Method::GET); |
| /// ``` |
| #[inline] |
| pub fn method(&self) -> &Method { |
| &self.head.method |
| } |
| |
| /// Returns a mutable reference to the associated HTTP method. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let mut request: Request<()> = Request::default(); |
| /// *request.method_mut() = Method::PUT; |
| /// assert_eq!(*request.method(), Method::PUT); |
| /// ``` |
| #[inline] |
| pub fn method_mut(&mut self) -> &mut Method { |
| &mut self.head.method |
| } |
| |
| /// Returns a reference to the associated URI. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request: Request<()> = Request::default(); |
| /// assert_eq!(*request.uri(), *"/"); |
| /// ``` |
| #[inline] |
| pub fn uri(&self) -> &Uri { |
| &self.head.uri |
| } |
| |
| /// Returns a mutable reference to the associated URI. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let mut request: Request<()> = Request::default(); |
| /// *request.uri_mut() = "/hello".parse().unwrap(); |
| /// assert_eq!(*request.uri(), *"/hello"); |
| /// ``` |
| #[inline] |
| pub fn uri_mut(&mut self) -> &mut Uri { |
| &mut self.head.uri |
| } |
| |
| /// Returns the associated version. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request: Request<()> = Request::default(); |
| /// assert_eq!(request.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 request: Request<()> = Request::default(); |
| /// *request.version_mut() = Version::HTTP_2; |
| /// assert_eq!(request.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 request: Request<()> = Request::default(); |
| /// assert!(request.headers().is_empty()); |
| /// ``` |
| #[inline] |
| pub fn headers(&self) -> &HeaderMap<HeaderValue> { |
| &self.head.headers |
| } |
| |
| /// Returns a mutable reference to the associated header field map. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// # use http::header::*; |
| /// let mut request: Request<()> = Request::default(); |
| /// request.headers_mut().insert(HOST, HeaderValue::from_static("world")); |
| /// assert!(!request.headers().is_empty()); |
| /// ``` |
| #[inline] |
| pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> { |
| &mut self.head.headers |
| } |
| |
| /// Returns a reference to the associated extensions. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request: Request<()> = Request::default(); |
| /// assert!(request.extensions().get::<i32>().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 request: Request<()> = Request::default(); |
| /// request.extensions_mut().insert("hello"); |
| /// assert_eq!(request.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 request: Request<String> = Request::default(); |
| /// assert!(request.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 request: Request<String> = Request::default(); |
| /// request.body_mut().push_str("hello world"); |
| /// assert!(!request.body().is_empty()); |
| /// ``` |
| #[inline] |
| pub fn body_mut(&mut self) -> &mut T { |
| &mut self.body |
| } |
| |
| /// Consumes the request, returning just the body. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::Request; |
| /// let request = Request::new(10); |
| /// let body = request.into_body(); |
| /// assert_eq!(body, 10); |
| /// ``` |
| #[inline] |
| pub fn into_body(self) -> T { |
| self.body |
| } |
| |
| /// Consumes the request returning the head and body parts. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request = Request::new(()); |
| /// let (parts, body) = request.into_parts(); |
| /// assert_eq!(parts.method, Method::GET); |
| /// ``` |
| #[inline] |
| pub fn into_parts(self) -> (Parts, T) { |
| (self.head, self.body) |
| } |
| |
| /// Consumes the request returning a new request with body mapped to the |
| /// return type of the passed in function. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// let request = Request::builder().body("some string").unwrap(); |
| /// let mapped_request: Request<&[u8]> = request.map(|b| { |
| /// assert_eq!(b, "some string"); |
| /// b.as_bytes() |
| /// }); |
| /// assert_eq!(mapped_request.body(), &"some string".as_bytes()); |
| /// ``` |
| #[inline] |
| pub fn map<F, U>(self, f: F) -> Request<U> |
| where |
| F: FnOnce(T) -> U, |
| { |
| Request { |
| body: f(self.body), |
| head: self.head, |
| } |
| } |
| } |
| |
| impl<T: Default> Default for Request<T> { |
| fn default() -> Request<T> { |
| Request::new(T::default()) |
| } |
| } |
| |
| impl<T: fmt::Debug> fmt::Debug for Request<T> { |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| f.debug_struct("Request") |
| .field("method", self.method()) |
| .field("uri", self.uri()) |
| .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 { |
| method: Method::default(), |
| uri: Uri::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("method", &self.method) |
| .field("uri", &self.uri) |
| .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 a `Request`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let req = request::Builder::new() |
| /// .method("POST") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| #[inline] |
| pub fn new() -> Builder { |
| Builder::default() |
| } |
| |
| /// Set the HTTP method for this request. |
| /// |
| /// This function will configure the HTTP method of the `Request` that will |
| /// be returned from `Builder::build`. |
| /// |
| /// By default this is `GET`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let req = Request::builder() |
| /// .method("POST") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn method<T>(self, method: T) -> Builder |
| where |
| Method: TryFrom<T>, |
| <Method as TryFrom<T>>::Error: Into<crate::Error>, |
| { |
| self.and_then(move |mut head| { |
| let method = TryFrom::try_from(method).map_err(Into::into)?; |
| head.method = method; |
| Ok(head) |
| }) |
| } |
| |
| /// Get the HTTP Method for this request. |
| /// |
| /// By default this is `GET`. If builder has error, returns None. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let mut req = Request::builder(); |
| /// assert_eq!(req.method_ref(),Some(&Method::GET)); |
| /// |
| /// req = req.method("POST"); |
| /// assert_eq!(req.method_ref(),Some(&Method::POST)); |
| /// ``` |
| pub fn method_ref(&self) -> Option<&Method> { |
| self.inner.as_ref().ok().map(|h| &h.method) |
| } |
| |
| /// Set the URI for this request. |
| /// |
| /// This function will configure the URI of the `Request` that will |
| /// be returned from `Builder::build`. |
| /// |
| /// By default this is `/`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let req = Request::builder() |
| /// .uri("https://www.rust-lang.org/") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn uri<T>(self, uri: T) -> Builder |
| where |
| Uri: TryFrom<T>, |
| <Uri as TryFrom<T>>::Error: Into<crate::Error>, |
| { |
| self.and_then(move |mut head| { |
| head.uri = TryFrom::try_from(uri).map_err(Into::into)?; |
| Ok(head) |
| }) |
| } |
| |
| /// Get the URI for this request |
| /// |
| /// By default this is `/`. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let mut req = Request::builder(); |
| /// assert_eq!(req.uri_ref().unwrap(), "/" ); |
| /// |
| /// req = req.uri("https://www.rust-lang.org/"); |
| /// assert_eq!(req.uri_ref().unwrap(), "https://www.rust-lang.org/" ); |
| /// ``` |
| pub fn uri_ref(&self) -> Option<&Uri> { |
| self.inner.as_ref().ok().map(|h| &h.uri) |
| } |
| |
| /// Set the HTTP version for this request. |
| /// |
| /// This function will configure the HTTP version of the `Request` that |
| /// will be returned from `Builder::build`. |
| /// |
| /// By default this is HTTP/1.1 |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let req = Request::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) |
| }) |
| } |
| |
| /// Get the HTTP version for this request |
| /// |
| /// By default this is HTTP/1.1. |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let mut req = Request::builder(); |
| /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_11 ); |
| /// |
| /// req = req.version(Version::HTTP_2); |
| /// assert_eq!(req.version_ref().unwrap(), &Version::HTTP_2 ); |
| /// ``` |
| pub fn version_ref(&self) -> Option<&Version> { |
| self.inner.as_ref().ok().map(|h| &h.version) |
| } |
| |
| /// Appends a header to this request 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 req = Request::builder() |
| /// .header("Accept", "text/html") |
| /// .header("X-Custom-Foo", "bar") |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn header<K, V>(self, key: K, value: V) -> Builder |
| where |
| HeaderName: TryFrom<K>, |
| <HeaderName as TryFrom<K>>::Error: Into<crate::Error>, |
| HeaderValue: TryFrom<V>, |
| <HeaderValue as TryFrom<V>>::Error: Into<crate::Error>, |
| { |
| self.and_then(move |mut head| { |
| let name = <HeaderName as TryFrom<K>>::try_from(key).map_err(Into::into)?; |
| let value = <HeaderValue as TryFrom<V>>::try_from(value).map_err(Into::into)?; |
| head.headers.append(name, value); |
| Ok(head) |
| }) |
| } |
| |
| /// Get header on this request builder. |
| /// when builder has error returns None |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::Request; |
| /// let req = Request::builder() |
| /// .header("Accept", "text/html") |
| /// .header("X-Custom-Foo", "bar"); |
| /// let headers = req.headers_ref().unwrap(); |
| /// assert_eq!( headers["Accept"], "text/html" ); |
| /// assert_eq!( headers["X-Custom-Foo"], "bar" ); |
| /// ``` |
| pub fn headers_ref(&self) -> Option<&HeaderMap<HeaderValue>> { |
| self.inner.as_ref().ok().map(|h| &h.headers) |
| } |
| |
| /// Get headers on this request builder. |
| /// |
| /// When builder has error returns None. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::{header::HeaderValue, Request}; |
| /// let mut req = Request::builder(); |
| /// { |
| /// let headers = req.headers_mut().unwrap(); |
| /// headers.insert("Accept", HeaderValue::from_static("text/html")); |
| /// headers.insert("X-Custom-Foo", HeaderValue::from_static("bar")); |
| /// } |
| /// let headers = req.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<HeaderValue>> { |
| self.inner.as_mut().ok().map(|h| &mut h.headers) |
| } |
| |
| /// Adds an extension to this builder |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// # use http::*; |
| /// |
| /// let req = Request::builder() |
| /// .extension("My Extension") |
| /// .body(()) |
| /// .unwrap(); |
| /// |
| /// assert_eq!(req.extensions().get::<&'static str>(), |
| /// Some(&"My Extension")); |
| /// ``` |
| pub fn extension<T>(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 request builder. |
| /// |
| /// If the builder has an error, this returns `None`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::Request; |
| /// let req = Request::builder().extension("My Extension").extension(5u32); |
| /// let extensions = req.extensions_ref().unwrap(); |
| /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension")); |
| /// assert_eq!(extensions.get::<u32>(), 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 request builder. |
| /// |
| /// If the builder has an error, this returns `None`. |
| /// |
| /// # Example |
| /// |
| /// ``` |
| /// # use http::Request; |
| /// let mut req = Request::builder().extension("My Extension"); |
| /// let mut extensions = req.extensions_mut().unwrap(); |
| /// assert_eq!(extensions.get::<&'static str>(), Some(&"My Extension")); |
| /// extensions.insert(5u32); |
| /// assert_eq!(extensions.get::<u32>(), 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 `Request`. |
| /// |
| /// # 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 request = Request::builder() |
| /// .body(()) |
| /// .unwrap(); |
| /// ``` |
| pub fn body<T>(self, body: T) -> Result<Request<T>> { |
| self.inner.map(move |head| { |
| Request { |
| head, |
| body, |
| } |
| }) |
| } |
| |
| // private |
| |
| fn and_then<F>(self, func: F) -> Self |
| where |
| F: FnOnce(Parts) -> Result<Parts> |
| { |
| 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 request = Request::builder().body("some string").unwrap(); |
| let mapped_request = request.map(|s| { |
| assert_eq!(s, "some string"); |
| 123u32 |
| }); |
| assert_eq!(mapped_request.body(), &123u32); |
| } |
| } |