Merge branch 'form'
This commit is contained in:
		| @@ -13,6 +13,7 @@ hyper = { version = "0.9" , default-features = false } | |||||||
| log = "0.3" | log = "0.3" | ||||||
| serde = "0.8" | serde = "0.8" | ||||||
| serde_json = "0.8" | serde_json = "0.8" | ||||||
|  | serde_urlencoded = "0.3" | ||||||
| url = "1.0" | url = "1.0" | ||||||
|  |  | ||||||
| [dependencies.native-tls] | [dependencies.native-tls] | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ use hyper::{Url}; | |||||||
|  |  | ||||||
| use serde::Serialize; | use serde::Serialize; | ||||||
| use serde_json; | use serde_json; | ||||||
|  | use serde_urlencoded; | ||||||
|  |  | ||||||
| use ::body::{self, Body}; | use ::body::{self, Body}; | ||||||
|  |  | ||||||
| @@ -94,7 +95,7 @@ pub struct RequestBuilder<'a> { | |||||||
|     _version: HttpVersion, |     _version: HttpVersion, | ||||||
|     headers: Headers, |     headers: Headers, | ||||||
|  |  | ||||||
|     body: Option<Body>, |     body: Option<::Result<Body>>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'a> RequestBuilder<'a> { | impl<'a> RequestBuilder<'a> { | ||||||
| @@ -122,7 +123,30 @@ impl<'a> RequestBuilder<'a> { | |||||||
|  |  | ||||||
|     /// Set the request body. |     /// Set the request body. | ||||||
|     pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder<'a> { |     pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder<'a> { | ||||||
|         self.body = Some(body.into()); |         self.body = Some(Ok(body.into())); | ||||||
|  |         self | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /// Send a form body. | ||||||
|  |     /// | ||||||
|  |     /// Sets the body to the url encoded serialization of the passed value, | ||||||
|  |     /// and also sets the `Content-Type: application/www-form-url-encoded` | ||||||
|  |     /// header. | ||||||
|  |     /// | ||||||
|  |     /// ```no_run | ||||||
|  |     /// # use std::collections::HashMap; | ||||||
|  |     /// let mut params = HashMap::new(); | ||||||
|  |     /// params.insert("lang", "rust"); | ||||||
|  |     /// | ||||||
|  |     /// let client = reqwest::Client::new().unwrap(); | ||||||
|  |     /// let res = client.post("http://httpbin.org") | ||||||
|  |     ///     .form(¶ms) | ||||||
|  |     ///     .send(); | ||||||
|  |     /// ``` | ||||||
|  |     pub fn form<T: Serialize>(mut self, form: &T) -> RequestBuilder<'a> { | ||||||
|  |         let body = serde_urlencoded::to_string(form).map_err(::Error::from); | ||||||
|  |         self.headers.set(ContentType::form_url_encoded()); | ||||||
|  |         self.body = Some(body.map(|b| b.into())); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -136,14 +160,15 @@ impl<'a> RequestBuilder<'a> { | |||||||
|     /// let mut map = HashMap::new(); |     /// let mut map = HashMap::new(); | ||||||
|     /// map.insert("lang", "rust"); |     /// map.insert("lang", "rust"); | ||||||
|     /// |     /// | ||||||
|     /// let res = reqwest::post("http://www.rust-lang.org") |     /// let client = reqwest::Client::new().unwrap(); | ||||||
|     ///     .json(map) |     /// let res = client.post("http://httpbin.org") | ||||||
|  |     ///     .json(&map) | ||||||
|     ///     .send(); |     ///     .send(); | ||||||
|     /// ``` |     /// ``` | ||||||
|     pub fn json<T: Serialize>(mut self, json: T) -> RequestBuilder<'a> { |     pub fn json<T: Serialize>(mut self, json: &T) -> RequestBuilder<'a> { | ||||||
|         let body = serde_json::to_vec(&json).expect("serde to_vec cannot fail"); |         let body = serde_json::to_vec(json).expect("serde to_vec cannot fail"); | ||||||
|         self.headers.set(ContentType::json()); |         self.headers.set(ContentType::json()); | ||||||
|         self.body = Some(body.into()); |         self.body = Some(Ok(body.into())); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -157,7 +182,10 @@ impl<'a> RequestBuilder<'a> { | |||||||
|         let mut method = self.method; |         let mut method = self.method; | ||||||
|         let mut url = try!(self.url); |         let mut url = try!(self.url); | ||||||
|         let mut headers = self.headers; |         let mut headers = self.headers; | ||||||
|         let mut body = self.body; |         let mut body = match self.body { | ||||||
|  |             Some(b) => Some(try!(b)), | ||||||
|  |             None => None, | ||||||
|  |         }; | ||||||
|  |  | ||||||
|         let mut redirect_count = 0; |         let mut redirect_count = 0; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								src/error.rs
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/error.rs
									
									
									
									
									
								
							| @@ -6,6 +6,11 @@ use std::fmt; | |||||||
| pub enum Error { | pub enum Error { | ||||||
|     /// An HTTP error from the `hyper` crate. |     /// An HTTP error from the `hyper` crate. | ||||||
|     Http(::hyper::Error), |     Http(::hyper::Error), | ||||||
|  |     /// An error trying to serialize a value. | ||||||
|  |     /// | ||||||
|  |     /// This may be serializing a value that is illegal in JSON or | ||||||
|  |     /// form-url-encoded bodies. | ||||||
|  |     Serialize(Box<StdError>), | ||||||
|     /// A request tried to redirect too many times. |     /// A request tried to redirect too many times. | ||||||
|     TooManyRedirects, |     TooManyRedirects, | ||||||
|     #[doc(hidden)] |     #[doc(hidden)] | ||||||
| @@ -16,6 +21,7 @@ impl fmt::Display for Error { | |||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|         match *self { |         match *self { | ||||||
|             Error::Http(ref e) => fmt::Display::fmt(e, f), |             Error::Http(ref e) => fmt::Display::fmt(e, f), | ||||||
|  |             Error::Serialize(ref e) => fmt::Display::fmt(e, f), | ||||||
|             Error::TooManyRedirects => { |             Error::TooManyRedirects => { | ||||||
|                 f.pad("Too many redirects") |                 f.pad("Too many redirects") | ||||||
|             }, |             }, | ||||||
| @@ -28,6 +34,7 @@ impl StdError for Error { | |||||||
|     fn description(&self) -> &str { |     fn description(&self) -> &str { | ||||||
|         match *self { |         match *self { | ||||||
|             Error::Http(ref e) => e.description(), |             Error::Http(ref e) => e.description(), | ||||||
|  |             Error::Serialize(ref e) => e.description(), | ||||||
|             Error::TooManyRedirects => "Too many redirects", |             Error::TooManyRedirects => "Too many redirects", | ||||||
|             Error::__DontMatchMe => unreachable!() |             Error::__DontMatchMe => unreachable!() | ||||||
|         } |         } | ||||||
| @@ -36,6 +43,7 @@ impl StdError for Error { | |||||||
|     fn cause(&self) -> Option<&StdError> { |     fn cause(&self) -> Option<&StdError> { | ||||||
|         match *self { |         match *self { | ||||||
|             Error::Http(ref e) => Some(e), |             Error::Http(ref e) => Some(e), | ||||||
|  |             Error::Serialize(ref e) => Some(&**e), | ||||||
|             Error::TooManyRedirects => None, |             Error::TooManyRedirects => None, | ||||||
|             Error::__DontMatchMe => unreachable!() |             Error::__DontMatchMe => unreachable!() | ||||||
|         } |         } | ||||||
| @@ -54,7 +62,11 @@ impl From<::url::ParseError> for Error { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | impl From<::serde_urlencoded::ser::Error> for Error { | ||||||
|  |     fn from(err: ::serde_urlencoded::ser::Error) -> Error { | ||||||
|  |         Error::Serialize(Box::new(err)) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| /// A `Result` alias where the `Err` case is `reqwest::Error`. | /// A `Result` alias where the `Err` case is `reqwest::Error`. | ||||||
| pub type Result<T> = ::std::result::Result<T, Error>; | pub type Result<T> = ::std::result::Result<T, Error>; | ||||||
|   | |||||||
							
								
								
									
										63
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								src/lib.rs
									
									
									
									
									
								
							| @@ -9,9 +9,9 @@ | |||||||
| //! to do for them. | //! to do for them. | ||||||
| //! | //! | ||||||
| //! - Uses system-native TLS | //! - Uses system-native TLS | ||||||
| //! - Plain bodies, JSON, urlencoded, multipart | //! - Plain bodies, JSON, urlencoded, (TODO: multipart) | ||||||
| //! - Customizable redirect policy | //! - (TODO: Customizable redirect policy) | ||||||
| //! - Cookies | //! - (TODO: Cookies) | ||||||
| //! | //! | ||||||
| //! The `reqwest::Client` is synchronous, making it a great fit for | //! The `reqwest::Client` is synchronous, making it a great fit for | ||||||
| //! applications that only require a few HTTP requests, and wish to handle | //! applications that only require a few HTTP requests, and wish to handle | ||||||
| @@ -32,12 +32,69 @@ | |||||||
| //! | //! | ||||||
| //! If you plan to perform multiple requests, it is best to create a [`Client`][client] | //! If you plan to perform multiple requests, it is best to create a [`Client`][client] | ||||||
| //! and reuse it, taking advantage of keep-alive connection pooling. | //! and reuse it, taking advantage of keep-alive connection pooling. | ||||||
|  | //! | ||||||
|  | //! ## Making POST requests (or setting request bodies) | ||||||
|  | //! | ||||||
|  | //! There are several ways you can set the body of a request. The basic one is | ||||||
|  | //! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the | ||||||
|  | //! exact raw bytes of what the body should be. It accepts various types, | ||||||
|  | //! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom | ||||||
|  | //! Reader, you can use the `reqwest::Body::new()` constructor. | ||||||
|  | //! | ||||||
|  | //! ```no_run | ||||||
|  | //! let client = reqwest::Client::new().unwrap(); | ||||||
|  | //! let res = client.post("http://httpbin.org/post") | ||||||
|  | //!     .body("the exact body that is sent") | ||||||
|  | //!     .send(); | ||||||
|  | //! ``` | ||||||
|  | //! | ||||||
|  | //! ### Forms | ||||||
|  | //! | ||||||
|  | //! It's very common to want to send form data in a request body. This can be | ||||||
|  | //! done with any type that can be serialized into form data. | ||||||
|  | //! | ||||||
|  | //! This can be an array of tuples, or a `HashMap`, or a custom type that | ||||||
|  | //! implements [`Serialize`][serde]. | ||||||
|  | //! | ||||||
|  | //! ```no_run | ||||||
|  | //! // This will POST a body of `foo=bar&baz=quux` | ||||||
|  | //! let params = [("foo", "bar"), ("baz", "quux")]; | ||||||
|  | //! let client = reqwest::Client::new().unwrap(); | ||||||
|  | //! let res = client.post("http://httpbin.org/post") | ||||||
|  | //!     .form(¶ms) | ||||||
|  | //!     .send(); | ||||||
|  | //! ``` | ||||||
|  | //! | ||||||
|  | //! ### JSON | ||||||
|  | //! | ||||||
|  | //! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in | ||||||
|  | //! a similar fashion the `form` method. It can take any value that can be | ||||||
|  | //! serialized into JSON. | ||||||
|  | //! | ||||||
|  | //! ```no_run | ||||||
|  | //! # use std::collections::HashMap; | ||||||
|  | //! // This will POST a body of `{"lang":"rust","body":"json"}` | ||||||
|  | //! let mut map = HashMap::new(); | ||||||
|  | //! map.insert("lang", "rust"); | ||||||
|  | //! map.insert("body", "json"); | ||||||
|  | //! | ||||||
|  | //! let client = reqwest::Client::new().unwrap(); | ||||||
|  | //! let res = client.post("http://httpbin.org/post") | ||||||
|  | //!     .json(&map) | ||||||
|  | //!     .send(); | ||||||
|  | //! ``` | ||||||
|  | //! | ||||||
|  | //! [hyper]: http://hyper.rs | ||||||
|  | //! [client]: ./struct.Client.html | ||||||
|  | //! [builder]: ./client/struct.RequestBuilder.html | ||||||
|  | //! [serde]: http://serde.rs | ||||||
| extern crate hyper; | extern crate hyper; | ||||||
|  |  | ||||||
| #[macro_use] extern crate log; | #[macro_use] extern crate log; | ||||||
| #[cfg(feature = "tls")] extern crate native_tls; | #[cfg(feature = "tls")] extern crate native_tls; | ||||||
| extern crate serde; | extern crate serde; | ||||||
| extern crate serde_json; | extern crate serde_json; | ||||||
|  | extern crate serde_urlencoded; | ||||||
| extern crate url; | extern crate url; | ||||||
|  |  | ||||||
| pub use hyper::header; | pub use hyper::header; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user