diff --git a/src/client/request.rs b/src/client/request.rs index cc65b9db1..735ce4937 100644 --- a/src/client/request.rs +++ b/src/client/request.rs @@ -16,7 +16,7 @@ use http::{ uri, Error as HttpError, HeaderMap, HeaderName, HeaderValue, HttpTryFrom, Method, Uri, Version, }; -use message::{Head, RequestHead}; +use message::{ConnectionType, Head, RequestHead}; use super::response::ClientResponse; use super::{pipeline, Connect, Connection, ConnectorError, SendRequestError}; @@ -367,7 +367,7 @@ impl ClientRequestBuilder { { { if let Some(parts) = parts(&mut self.head, &self.err) { - parts.set_upgrade(); + parts.set_connection_type(ConnectionType::Upgrade); } } self.set_header(header::UPGRADE, value) @@ -377,7 +377,7 @@ impl ClientRequestBuilder { #[inline] pub fn close(&mut self) -> &mut Self { if let Some(parts) = parts(&mut self.head, &self.err) { - parts.force_close(); + parts.set_connection_type(ConnectionType::Close); } self } diff --git a/src/h1/decoder.rs b/src/h1/decoder.rs index 12008a777..12dfe1657 100644 --- a/src/h1/decoder.rs +++ b/src/h1/decoder.rs @@ -10,7 +10,7 @@ use client::ClientResponse; use error::ParseError; use http::header::{HeaderName, HeaderValue}; use http::{header, HeaderMap, HttpTryFrom, Method, StatusCode, Uri, Version}; -use message::Head; +use message::{ConnectionType, Head}; use request::Request; const MAX_BUFFER_SIZE: usize = 131_072; @@ -164,11 +164,15 @@ pub(crate) trait MessageTypeDecoder: Sized { impl MessageTypeDecoder for Request { fn keep_alive(&mut self) { - self.inner_mut().head.set_keep_alive() + self.inner_mut() + .head + .set_connection_type(ConnectionType::KeepAlive) } fn force_close(&mut self) { - self.inner_mut().head.force_close() + self.inner_mut() + .head + .set_connection_type(ConnectionType::Close) } fn headers_mut(&mut self) -> &mut HeaderMap { @@ -242,11 +246,11 @@ impl MessageTypeDecoder for Request { impl MessageTypeDecoder for ClientResponse { fn keep_alive(&mut self) { - self.head.set_keep_alive(); + self.head.set_connection_type(ConnectionType::KeepAlive); } fn force_close(&mut self) { - self.head.force_close(); + self.head.set_connection_type(ConnectionType::Close); } fn headers_mut(&mut self) -> &mut HeaderMap { diff --git a/src/lib.rs b/src/lib.rs index 57ff5df78..3024b753f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -175,4 +175,5 @@ pub mod http { pub use header::*; } pub use header::ContentEncoding; + pub use message::ConnectionType; } diff --git a/src/message.rs b/src/message.rs index e7ce22fcd..03e18f082 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,4 +1,4 @@ -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use std::collections::VecDeque; use std::rc::Rc; @@ -8,46 +8,36 @@ use extensions::Extensions; use payload::Payload; use uri::Url; +/// Represents various types of connection +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum ConnectionType { + /// Close connection after response + Close, + /// Keep connection alive after response + KeepAlive, + /// Connection is upgraded to different type + Upgrade, +} + #[doc(hidden)] pub trait Head: Default + 'static { fn clear(&mut self); - fn flags(&self) -> MessageFlags; + /// Connection type + fn connection_type(&self) -> ConnectionType; - fn flags_mut(&mut self) -> &mut MessageFlags; + /// Set connection type of the message + fn set_connection_type(&mut self, ctype: ConnectionType); + + fn upgrade(&self) -> bool { + self.connection_type() == ConnectionType::Upgrade + } + + fn keep_alive(&self) -> bool { + self.connection_type() == ConnectionType::KeepAlive + } fn pool() -> &'static MessagePool; - - /// Set upgrade - fn set_upgrade(&mut self) { - *self.flags_mut() = MessageFlags::UPGRADE; - } - - /// Check if request is upgrade request - fn upgrade(&self) -> bool { - self.flags().contains(MessageFlags::UPGRADE) - } - - /// Set keep-alive - fn set_keep_alive(&mut self) { - *self.flags_mut() = MessageFlags::KEEP_ALIVE; - } - - /// Check if request is keep-alive - fn keep_alive(&self) -> bool; - - /// Set force-close connection - fn force_close(&mut self) { - *self.flags_mut() = MessageFlags::FORCE_CLOSE; - } -} - -bitflags! { - pub struct MessageFlags: u8 { - const KEEP_ALIVE = 0b0000_0001; - const FORCE_CLOSE = 0b0000_0010; - const UPGRADE = 0b0000_0100; - } } pub struct RequestHead { @@ -55,7 +45,7 @@ pub struct RequestHead { pub method: Method, pub version: Version, pub headers: HeaderMap, - pub(crate) flags: MessageFlags, + ctype: Option, } impl Default for RequestHead { @@ -65,33 +55,28 @@ impl Default for RequestHead { method: Method::default(), version: Version::HTTP_11, headers: HeaderMap::with_capacity(16), - flags: MessageFlags::empty(), + ctype: None, } } } impl Head for RequestHead { fn clear(&mut self) { + self.ctype = None; self.headers.clear(); - self.flags = MessageFlags::empty(); } - fn flags(&self) -> MessageFlags { - self.flags + fn set_connection_type(&mut self, ctype: ConnectionType) { + self.ctype = Some(ctype) } - fn flags_mut(&mut self) -> &mut MessageFlags { - &mut self.flags - } - - /// Check if request is keep-alive - fn keep_alive(&self) -> bool { - if self.flags().contains(MessageFlags::FORCE_CLOSE) { - false - } else if self.flags().contains(MessageFlags::KEEP_ALIVE) { - true + fn connection_type(&self) -> ConnectionType { + if let Some(ct) = self.ctype { + ct + } else if self.version <= Version::HTTP_11 { + ConnectionType::Close } else { - self.version <= Version::HTTP_11 + ConnectionType::KeepAlive } } @@ -105,7 +90,7 @@ pub struct ResponseHead { pub status: StatusCode, pub headers: HeaderMap, pub reason: Option<&'static str>, - pub(crate) flags: MessageFlags, + pub(crate) ctype: Option, } impl Default for ResponseHead { @@ -115,34 +100,29 @@ impl Default for ResponseHead { status: StatusCode::OK, headers: HeaderMap::with_capacity(16), reason: None, - flags: MessageFlags::empty(), + ctype: None, } } } impl Head for ResponseHead { fn clear(&mut self) { + self.ctype = None; self.reason = None; self.headers.clear(); - self.flags = MessageFlags::empty(); } - fn flags(&self) -> MessageFlags { - self.flags + fn set_connection_type(&mut self, ctype: ConnectionType) { + self.ctype = Some(ctype) } - fn flags_mut(&mut self) -> &mut MessageFlags { - &mut self.flags - } - - /// Check if response is keep-alive - fn keep_alive(&self) -> bool { - if self.flags().contains(MessageFlags::FORCE_CLOSE) { - false - } else if self.flags().contains(MessageFlags::KEEP_ALIVE) { - true + fn connection_type(&self) -> ConnectionType { + if let Some(ct) = self.ctype { + ct + } else if self.version <= Version::HTTP_11 { + ConnectionType::Close } else { - self.version <= Version::HTTP_11 + ConnectionType::KeepAlive } } @@ -172,7 +152,6 @@ pub struct Message { pub extensions: RefCell, pub payload: RefCell>, pub(crate) pool: &'static MessagePool, - pub(crate) flags: Cell, } impl Message { @@ -181,7 +160,6 @@ impl Message { pub fn reset(&mut self) { self.head.clear(); self.extensions.borrow_mut().clear(); - self.flags.set(MessageFlags::empty()); *self.payload.borrow_mut() = None; } } @@ -193,7 +171,6 @@ impl Default for Message { url: Url::default(), head: T::default(), status: StatusCode::OK, - flags: Cell::new(MessageFlags::empty()), payload: RefCell::new(None), extensions: RefCell::new(Extensions::new()), } diff --git a/src/response.rs b/src/response.rs index 542d4963e..f2ed72925 100644 --- a/src/response.rs +++ b/src/response.rs @@ -15,7 +15,7 @@ use serde_json; use body::{Body, BodyStream, MessageBody}; use error::Error; use header::{Header, IntoHeaderValue}; -use message::{Head, MessageFlags, ResponseHead}; +use message::{ConnectionType, Head, ResponseHead}; /// max write buffer size 64k pub(crate) const MAX_WRITE_BUFFER_SIZE: usize = 65_536; @@ -360,7 +360,7 @@ impl ResponseBuilder { #[inline] pub fn keep_alive(&mut self) -> &mut Self { if let Some(parts) = parts(&mut self.response, &self.err) { - parts.head.set_keep_alive(); + parts.head.set_connection_type(ConnectionType::KeepAlive); } self } @@ -369,7 +369,7 @@ impl ResponseBuilder { #[inline] pub fn upgrade(&mut self) -> &mut Self { if let Some(parts) = parts(&mut self.response, &self.err) { - parts.head.set_upgrade(); + parts.head.set_connection_type(ConnectionType::Upgrade); } self } @@ -378,7 +378,7 @@ impl ResponseBuilder { #[inline] pub fn force_close(&mut self) -> &mut Self { if let Some(parts) = parts(&mut self.response, &self.err) { - parts.head.force_close(); + parts.head.set_connection_type(ConnectionType::Close); } self } @@ -698,7 +698,7 @@ impl InnerResponse { version: Version::default(), headers: HeaderMap::with_capacity(16), reason: None, - flags: MessageFlags::empty(), + ctype: None, }, pool, response_size: 0,