use std::fmt; use Url; use header::Headers; use http::{Body, RequestHead}; use method::Method; use uri::Uri; use version::HttpVersion; /// A client request to a remote server. pub struct Request { method: Method, url: Url, version: HttpVersion, headers: Headers, body: Option, } impl Request { /// Construct a new Request. #[inline] pub fn new(method: Method, url: Url) -> Request { Request { method: method, url: url, version: HttpVersion::default(), headers: Headers::new(), body: None, } } /// Read the Request Url. #[inline] pub fn url(&self) -> &Url { &self.url } /// Readthe 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 } /// 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 `Url` of this request. #[inline] pub fn set_url(&mut self, url: Url) { self.url = url; } /// 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>(&mut self, body: T) { self.body = Some(body.into()); } } impl fmt::Debug for Request { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Request") .field("method", &self.method) .field("url", &self.url) .field("version", &self.version) .field("headers", &self.headers) .finish() } } pub fn split(req: Request) -> (RequestHead, Option) { let uri = Uri::new(&req.url[::url::Position::BeforePath..::url::Position::AfterQuery]).expect("url is 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::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) -> Vec { let req = req.start().unwrap(); let message = req.message; let mut message = message.downcast::().ok().unwrap(); message.flush_outgoing().unwrap(); let stream = *message .into_inner().downcast::().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")); } #[test] fn test_post_chunked_with_encoding() { let url = Url::parse("http://example.dom").unwrap(); let mut req = Request::with_connector( Post, url, &mut MockConnector ).unwrap(); req.headers_mut().set(TransferEncoding(vec![Encoding::Chunked])); let bytes = run_request(req); let s = from_utf8(&bytes[..]).unwrap(); assert!(!s.contains("Content-Length:")); assert!(s.contains("Transfer-Encoding:")); } #[test] fn test_write_error_closes() { let url = Url::parse("http://hyper.rs").unwrap(); let req = Request::with_connector( Get, url, &mut MockConnector ).unwrap(); let mut req = req.start().unwrap(); req.message.downcast_mut::().unwrap() .get_mut().downcast_mut::().unwrap() .error_on_write = true; req.write(b"foo").unwrap(); assert!(req.flush().is_err()); assert!(req.message.downcast_ref::().unwrap() .get_ref().downcast_ref::().unwrap() .is_closed); } */ }