refactor(http): merge Request and Response from server and client
Request and Response are now visible from:
- hyper::{Request, Response}
- hyper::server::{Request, Response}
- hyper::client::{Request, Response}
They truly exist in the http module, but are re-exported to reduce the number of breaking changes.
request::new and response::new were renamed to ::from_wire to reduce confusion with Request::new
and Response::new. See issue #1126
Request now has an optional Body, because not all requests have bodies.
Use body_ref() to determine if a body exists.
Use body() to take the body, or construct one if no body exists.
Closes #1155
BREAKING CHANGE: Response::body() now consumes the response
			
			
This commit is contained in:
		| @@ -22,19 +22,19 @@ pub use tokio_service::Service; | ||||
|  | ||||
| use header::{Headers, Host}; | ||||
| use http::{self, TokioBody}; | ||||
| use http::response; | ||||
| use http::request; | ||||
| use method::Method; | ||||
| use self::pool::{Pool, Pooled}; | ||||
| use uri::{self, Uri}; | ||||
|  | ||||
| pub use http::response::Response; | ||||
| pub use http::request::Request; | ||||
| pub use self::connect::{HttpConnector, Connect}; | ||||
| pub use self::request::Request; | ||||
| pub use self::response::Response; | ||||
|  | ||||
| mod connect; | ||||
| mod dns; | ||||
| mod pool; | ||||
| mod request; | ||||
| mod response; | ||||
|  | ||||
| /// A Client to make outgoing HTTP requests. | ||||
| // If the Connector is clone, then the Client can be clone easily. | ||||
| @@ -198,8 +198,8 @@ where C: Connect, | ||||
|         }); | ||||
|         FutureResponse(Box::new(req.map(|msg| { | ||||
|             match msg { | ||||
|                 Message::WithoutBody(head) => response::new(head, None), | ||||
|                 Message::WithBody(head, body) => response::new(head, Some(body.into())), | ||||
|                 Message::WithoutBody(head) => response::from_wire(head, None), | ||||
|                 Message::WithBody(head, body) => response::from_wire(head, Some(body.into())), | ||||
|             } | ||||
|         }))) | ||||
|     } | ||||
|   | ||||
| @@ -1,216 +0,0 @@ | ||||
| use std::fmt; | ||||
|  | ||||
| use header::Headers; | ||||
| use http::{Body, RequestHead}; | ||||
| use method::Method; | ||||
| use uri::{self, Uri}; | ||||
| use version::HttpVersion; | ||||
|  | ||||
| /// A client request to a remote server. | ||||
| pub struct Request<B = Body> { | ||||
|     method: Method, | ||||
|     uri: Uri, | ||||
|     version: HttpVersion, | ||||
|     headers: Headers, | ||||
|     body: Option<B>, | ||||
|     is_proxy: bool, | ||||
| } | ||||
|  | ||||
| impl<B> Request<B> { | ||||
|     /// Construct a new Request. | ||||
|     #[inline] | ||||
|     pub fn new(method: Method, uri: Uri) -> Request<B> { | ||||
|         Request { | ||||
|             method: method, | ||||
|             uri: uri, | ||||
|             version: HttpVersion::default(), | ||||
|             headers: Headers::new(), | ||||
|             body: None, | ||||
|             is_proxy: false, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Read the Request Uri. | ||||
|     #[inline] | ||||
|     pub fn uri(&self) -> &Uri { &self.uri } | ||||
|      | ||||
|     /// Read the Request Version. | ||||
|     #[inline] | ||||
|     pub fn version(&self) -> HttpVersion { self.version } | ||||
|  | ||||
|     /// Read the Request headers. | ||||
|     #[inline] | ||||
|     pub fn headers(&self) -> &Headers { &self.headers } | ||||
|  | ||||
|     /// Read the Request method. | ||||
|     #[inline] | ||||
|     pub fn method(&self) -> &Method { &self.method } | ||||
|  | ||||
|     /// Read the Request body. | ||||
|     #[inline] | ||||
|     pub fn body(&self) -> Option<&B> { self.body.as_ref() } | ||||
|      | ||||
|     /// Set the Method of this request. | ||||
|     #[inline] | ||||
|     pub fn set_method(&mut self, method: Method) { self.method = method; } | ||||
|  | ||||
|     /// Get a mutable reference to the Request headers. | ||||
|     #[inline] | ||||
|     pub fn headers_mut(&mut self) -> &mut Headers { &mut self.headers } | ||||
|  | ||||
|     /// Set the `Uri` of this request. | ||||
|     #[inline] | ||||
|     pub fn set_uri(&mut self, uri: Uri) { self.uri = uri; } | ||||
|  | ||||
|     /// Set the `HttpVersion` of this request. | ||||
|     #[inline] | ||||
|     pub fn set_version(&mut self, version: HttpVersion) { self.version = version; } | ||||
|  | ||||
|     /// Set the body of the request. | ||||
|     #[inline] | ||||
|     pub fn set_body<T: Into<B>>(&mut self, body: T) { self.body = Some(body.into()); } | ||||
|  | ||||
|     /// Set that the URI should use the absolute form. | ||||
|     /// | ||||
|     /// This is only needed when talking to HTTP/1 proxies to URLs not | ||||
|     /// protected by TLS. | ||||
|     #[inline] | ||||
|     pub fn set_proxy(&mut self, is_proxy: bool) { self.is_proxy = is_proxy; } | ||||
| } | ||||
|  | ||||
| impl<B> fmt::Debug for Request<B> { | ||||
|     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) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn split<B>(req: Request<B>) -> (RequestHead, Option<B>) { | ||||
|     let uri = if req.is_proxy { | ||||
|         req.uri | ||||
|     } else { | ||||
|         uri::origin_form(&req.uri) | ||||
|     }; | ||||
|     let head = RequestHead { | ||||
|         subject: ::http::RequestLine(req.method, uri), | ||||
|         headers: req.headers, | ||||
|         version: req.version, | ||||
|     }; | ||||
|     (head, req.body) | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| mod tests { | ||||
|     /* | ||||
|     use std::io::Write; | ||||
|     use std::str::from_utf8; | ||||
|     use Url; | ||||
|     use method::Method::{Get, Head, Post}; | ||||
|     use mock::{MockStream, MockConnector}; | ||||
|     use net::Fresh; | ||||
|     use header::{ContentLength,TransferEncoding,Encoding}; | ||||
|     use url::form_urlencoded; | ||||
|     use super::Request; | ||||
|     use http::h1::Http11Message; | ||||
|  | ||||
|     fn run_request(req: Request<Fresh>) -> Vec<u8> { | ||||
|         let req = req.start().unwrap(); | ||||
|         let message = req.message; | ||||
|         let mut message = message.downcast::<Http11Message>().ok().unwrap(); | ||||
|         message.flush_outgoing().unwrap(); | ||||
|         let stream = *message | ||||
|             .into_inner().downcast::<MockStream>().ok().unwrap(); | ||||
|         stream.write | ||||
|     } | ||||
|  | ||||
|     fn assert_no_body(s: &str) { | ||||
|         assert!(!s.contains("Content-Length:")); | ||||
|         assert!(!s.contains("Transfer-Encoding:")); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_get_empty_body() { | ||||
|         let req = Request::with_connector( | ||||
|             Get, Url::parse("http://example.dom").unwrap(), &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert_no_body(s); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_head_empty_body() { | ||||
|         let req = Request::with_connector( | ||||
|             Head, Url::parse("http://example.dom").unwrap(), &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert_no_body(s); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_url_query() { | ||||
|         let url = Url::parse("http://example.dom?q=value").unwrap(); | ||||
|         let req = Request::with_connector( | ||||
|             Get, url, &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert!(s.contains("?q=value")); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_post_content_length() { | ||||
|         let url = Url::parse("http://example.dom").unwrap(); | ||||
|         let mut req = Request::with_connector( | ||||
|             Post, url, &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let mut body = String::new(); | ||||
|         form_urlencoded::Serializer::new(&mut body).append_pair("q", "value"); | ||||
|         req.headers_mut().set(ContentLength(body.len() as u64)); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert!(s.contains("Content-Length:")); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_post_chunked() { | ||||
|         let url = Url::parse("http://example.dom").unwrap(); | ||||
|         let req = Request::with_connector( | ||||
|             Post, url, &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert!(!s.contains("Content-Length:")); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_host_header() { | ||||
|         let url = Url::parse("http://example.dom").unwrap(); | ||||
|         let req = Request::with_connector( | ||||
|             Get, url, &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         assert!(s.contains("Host: example.dom")); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_proxy() { | ||||
|         let url = Url::parse("http://example.dom").unwrap(); | ||||
|         let mut req = Request::with_connector( | ||||
|             Get, url, &mut MockConnector | ||||
|         ).unwrap(); | ||||
|         req.message.set_proxied(true); | ||||
|         let bytes = run_request(req); | ||||
|         let s = from_utf8(&bytes[..]).unwrap(); | ||||
|         let request_line = "GET http://example.dom/ HTTP/1.1"; | ||||
|         assert_eq!(&s[..request_line.len()], request_line); | ||||
|         assert!(s.contains("Host: example.dom")); | ||||
|     } | ||||
|     */ | ||||
| } | ||||
| @@ -1,65 +0,0 @@ | ||||
| use std::fmt; | ||||
|  | ||||
| use header; | ||||
| use http::{self, RawStatus, Body}; | ||||
| use status; | ||||
| use version; | ||||
|  | ||||
| pub fn new(incoming: http::ResponseHead, body: Option<Body>) -> Response { | ||||
|     trace!("Response::new"); | ||||
|     let status = status::StatusCode::from_u16(incoming.subject.0); | ||||
|     debug!("version={:?}, status={:?}", incoming.version, status); | ||||
|     debug!("headers={:?}", incoming.headers); | ||||
|  | ||||
|     Response { | ||||
|         status: status, | ||||
|         version: incoming.version, | ||||
|         headers: incoming.headers, | ||||
|         status_raw: incoming.subject, | ||||
|         body: body, | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /// A response for a client request to a remote server. | ||||
| pub struct Response { | ||||
|     status: status::StatusCode, | ||||
|     headers: header::Headers, | ||||
|     version: version::HttpVersion, | ||||
|     status_raw: RawStatus, | ||||
|     body: Option<Body>, | ||||
| } | ||||
|  | ||||
| impl Response { | ||||
|     /// Get the headers from the server. | ||||
|     #[inline] | ||||
|     pub fn headers(&self) -> &header::Headers { &self.headers } | ||||
|  | ||||
|     /// Get the status from the server. | ||||
|     #[inline] | ||||
|     pub fn status(&self) -> status::StatusCode { self.status } | ||||
|  | ||||
|     /// Get the raw status code and reason. | ||||
|     #[inline] | ||||
|     pub fn status_raw(&self) -> &RawStatus { &self.status_raw } | ||||
|  | ||||
|     /// Get the HTTP version of this response from the server. | ||||
|     #[inline] | ||||
|     pub fn version(&self) -> version::HttpVersion { self.version } | ||||
|  | ||||
|     /// Take the `Body` of this response. | ||||
|     #[inline] | ||||
|     pub fn body(mut self) -> Body { | ||||
|         self.body.take().unwrap_or(Body::empty()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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) | ||||
|             .finish() | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user