diff --git a/src/httpmessage.rs b/src/httpmessage.rs index c0c2c4642..50c1d25fc 100644 --- a/src/httpmessage.rs +++ b/src/httpmessage.rs @@ -16,41 +16,6 @@ pub enum ConnectionType { Upgrade, } -pub trait Message { - - fn version(&self) -> Version; - - fn headers(&self) -> &HeaderMap; - - /// Checks if a connection is expecting a `100 Continue` before sending its body. - #[inline] - fn expecting_continue(&self) -> bool { - if self.version() == Version::HTTP_11 { - if let Some(hdr) = self.headers().get(header::EXPECT) { - if let Ok(hdr) = hdr.to_str() { - return hdr.to_lowercase().contains("continue") - } - } - } - false - } - - fn is_chunked(&self) -> Result { - if let Some(encodings) = self.headers().get(header::TRANSFER_ENCODING) { - if let Ok(s) = encodings.to_str() { - return Ok(s.to_lowercase().contains("chunked")) - } else { - Err(io::Error::new( - io::ErrorKind::Other, - "Request with transfer-encoding header, but not chunked")) - } - } else { - Ok(false) - } - } -} - - #[derive(Debug)] /// An HTTP Request pub struct HttpRequest { @@ -61,15 +26,6 @@ pub struct HttpRequest { params: Params, } -impl Message for HttpRequest { - fn version(&self) -> Version { - self.version - } - fn headers(&self) -> &HeaderMap { - &self.headers - } -} - impl HttpRequest { /// Construct a new Request. #[inline] @@ -87,18 +43,20 @@ impl HttpRequest { #[inline] pub fn uri(&self) -> &Uri { &self.uri } - /// Read the Request Version. - #[inline] - pub fn version(&self) -> Version { self.version } - - /// Read the Request headers. - #[inline] - pub fn headers(&self) -> &HeaderMap { &self.headers } - /// Read the Request method. #[inline] pub fn method(&self) -> &Method { &self.method } + /// Read the Request Version. + pub fn version(&self) -> Version { + self.version + } + + /// Read the Request Headers. + pub fn headers(&self) -> &HeaderMap { + &self.headers + } + // /// The remote socket address of this request // /// // /// This is an `Option`, because some underlying transports may not have @@ -169,6 +127,20 @@ impl HttpRequest { } false } + + pub fn is_chunked(&self) -> Result { + if let Some(encodings) = self.headers().get(header::TRANSFER_ENCODING) { + if let Ok(s) = encodings.to_str() { + return Ok(s.to_lowercase().contains("chunked")) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "Request with transfer-encoding header, but not chunked")) + } + } else { + Ok(false) + } + } } /// Represents various types of http message body. @@ -200,7 +172,7 @@ impl Body { #[derive(Debug)] /// An HTTP Response pub struct HttpResponse { - pub version: Version, + pub version: Option, pub headers: HeaderMap, pub status: StatusCode, reason: Option<&'static str>, @@ -209,15 +181,6 @@ pub struct HttpResponse { connection_type: Option, } -impl Message for HttpResponse { - fn version(&self) -> Version { - self.version - } - fn headers(&self) -> &HeaderMap { - &self.headers - } -} - impl HttpResponse { #[inline] @@ -232,7 +195,7 @@ impl HttpResponse { #[inline] pub fn new(status: StatusCode, body: Body) -> HttpResponse { HttpResponse { - version: Version::HTTP_11, + version: None, headers: Default::default(), status: status, reason: None, @@ -245,7 +208,7 @@ impl HttpResponse { /// Get the HTTP version of this response. #[inline] - pub fn version(&self) -> Version { + pub fn version(&self) -> Option { self.version } @@ -344,9 +307,18 @@ impl From for HttpResponse { } } +impl, E: Into> From> for HttpResponse { + fn from(res: Result) -> Self { + match res { + Ok(val) => val.into(), + Err(err) => err.into(), + } + } +} + #[derive(Debug)] struct Parts { - version: Version, + version: Option, headers: HeaderMap, status: StatusCode, reason: Option<&'static str>, @@ -357,7 +329,7 @@ struct Parts { impl Parts { fn new(status: StatusCode) -> Self { Parts { - version: Version::default(), + version: None, headers: HeaderMap::new(), status: status, reason: None, @@ -383,7 +355,7 @@ impl Builder { #[inline] pub fn version(&mut self, version: Version) -> &mut Self { if let Some(parts) = parts(&mut self.parts, &self.err) { - parts.version = version; + parts.version = Some(version); } self } diff --git a/src/reader.rs b/src/reader.rs index 332444321..f93a6bb2a 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -9,8 +9,8 @@ use tokio_io::AsyncRead; use error::{Error, Result}; use decode::Decoder; +use httpmessage::HttpRequest; use payload::{Payload, PayloadSender}; -use httpmessage::{Message, HttpRequest}; const MAX_HEADERS: usize = 100; const INIT_BUFFER_SIZE: usize = 8192; diff --git a/src/task.rs b/src/task.rs index 96d839fab..30ecd4f5b 100644 --- a/src/task.rs +++ b/src/task.rs @@ -56,9 +56,9 @@ pub struct Task { impl Task { - pub fn reply(req: HttpRequest, msg: HttpResponse) -> Self { + pub fn reply>(req: HttpRequest, response: R) -> Self { let mut frames = VecDeque::new(); - frames.push_back(Frame::Message(req, msg)); + frames.push_back(Frame::Message(req, response.into())); frames.push_back(Frame::Payload(None)); Task { @@ -92,6 +92,7 @@ impl Task { let mut extra = 0; let body = msg.replace_body(Body::Empty); + let version = msg.version().unwrap_or_else(|| req.version()); match body { Body::Empty => { @@ -122,7 +123,7 @@ impl Task { } Body::Streaming => { if msg.chunked() { - if msg.version < Version::HTTP_11 { + if version < Version::HTTP_11 { error!("Chunked transfer encoding is forbidden for {:?}", msg.version); } msg.headers.remove(CONTENT_LENGTH); @@ -144,10 +145,10 @@ impl Task { } // keep-alive else if msg.keep_alive().unwrap_or_else(|| req.keep_alive()) { - if msg.version < Version::HTTP_11 { + if version < Version::HTTP_11 { msg.headers.insert(CONNECTION, HeaderValue::from_static("keep-alive")); } - } else if msg.version >= Version::HTTP_11 { + } else if version >= Version::HTTP_11 { msg.headers.insert(CONNECTION, HeaderValue::from_static("close")); } @@ -155,7 +156,7 @@ impl Task { let init_cap = 100 + msg.headers.len() * AVERAGE_HEADER_SIZE + extra; self.buffer.reserve(init_cap); - if msg.version == Version::HTTP_11 && msg.status == StatusCode::OK { + if version == Version::HTTP_11 && msg.status == StatusCode::OK { self.buffer.extend(b"HTTP/1.1 200 OK\r\n"); } else { let _ = write!(self.buffer, "{:?} {}\r\n", msg.version, msg.status);