From 1daf50095abb06606709c40673f9154c1b7def01 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 15 Dec 2017 20:00:12 -0800 Subject: [PATCH] cleanup response --- src/handler.rs | 5 ++ src/httpresponse.rs | 187 ++++++++++++++++++++++---------------------- src/pipeline.rs | 39 ++++----- 3 files changed, 116 insertions(+), 115 deletions(-) diff --git a/src/handler.rs b/src/handler.rs index 6ea28dec4..f0fbb1ea3 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -110,6 +110,7 @@ impl Responder for HttpResponse { type Item = Reply; type Error = Error; + #[inline] fn respond_to(self, _: HttpRequest) -> Result { Ok(Reply(ReplyItem::Message(self))) } @@ -117,6 +118,7 @@ impl Responder for HttpResponse { impl From for Reply { + #[inline] fn from(resp: HttpResponse) -> Reply { Reply(ReplyItem::Message(resp)) } @@ -152,6 +154,7 @@ impl>, S: 'static> Responder for HttpContext< type Item = Reply; type Error = Error; + #[inline] fn respond_to(self, _: HttpRequest) -> Result { Ok(Reply(ReplyItem::Actor(Box::new(self)))) } @@ -159,6 +162,7 @@ impl>, S: 'static> Responder for HttpContext< impl>, S: 'static> From> for Reply { + #[inline] fn from(ctx: HttpContext) -> Reply { Reply(ReplyItem::Actor(Box::new(ctx))) } @@ -169,6 +173,7 @@ impl Responder for Box> type Item = Reply; type Error = Error; + #[inline] fn respond_to(self, _: HttpRequest) -> Result { Ok(Reply(ReplyItem::Future(self))) } diff --git a/src/httpresponse.rs b/src/httpresponse.rs index e98606335..b7f9d8301 100644 --- a/src/httpresponse.rs +++ b/src/httpresponse.rs @@ -29,86 +29,6 @@ pub enum ConnectionType { Upgrade, } -#[derive(Debug)] -struct InnerHttpResponse { - version: Option, - headers: HeaderMap, - status: StatusCode, - reason: Option<&'static str>, - body: Body, - chunked: bool, - encoding: ContentEncoding, - connection_type: Option, - response_size: u64, - error: Option, -} - -impl InnerHttpResponse { - - #[inline] - fn new(status: StatusCode, body: Body) -> InnerHttpResponse { - InnerHttpResponse { - version: None, - headers: HeaderMap::with_capacity(8), - status: status, - reason: None, - body: body, - chunked: false, - encoding: ContentEncoding::Auto, - connection_type: None, - response_size: 0, - error: None, - } - } - -} - -impl Default for InnerHttpResponse { - - fn default() -> InnerHttpResponse { - InnerHttpResponse::new(StatusCode::OK, Body::Empty) - } -} - -/// Internal use only! unsafe -struct Pool(VecDeque>); - -thread_local!(static POOL: RefCell = RefCell::new(Pool::new())); - -impl Pool { - fn new() -> Pool { - Pool(VecDeque::with_capacity(128)) - } - - fn get() -> Box { - POOL.with(|pool| { - if let Some(resp) = pool.borrow_mut().0.pop_front() { - resp - } else { - Box::new(InnerHttpResponse::default()) - } - }) - } - - #[cfg_attr(feature = "cargo-clippy", allow(boxed_local))] - fn release(mut inner: Box) { - POOL.with(|pool| { - if pool.borrow().0.len() < 128 { - inner.version.take(); - inner.headers.clear(); - inner.chunked = false; - inner.reason.take(); - inner.body = Body::Empty; - inner.encoding = ContentEncoding::Auto; - inner.connection_type.take(); - inner.response_size = 0; - inner.error.take(); - pool.borrow_mut().0.push_front(inner); - } - }) - } -} - /// An HTTP Response pub struct HttpResponse(Option>); @@ -123,27 +43,22 @@ impl Drop for HttpResponse { impl HttpResponse { #[inline(always)] + #[cfg_attr(feature = "cargo-clippy", allow(inline_always))] fn get_ref(&self) -> &InnerHttpResponse { self.0.as_ref().unwrap() } #[inline(always)] + #[cfg_attr(feature = "cargo-clippy", allow(inline_always))] fn get_mut(&mut self) -> &mut InnerHttpResponse { self.0.as_mut().unwrap() } - #[inline] - fn from_inner(inner: Box) -> HttpResponse { - HttpResponse(Some(inner)) - } - /// Create http response builder with specific status. #[inline] pub fn build(status: StatusCode) -> HttpResponseBuilder { - let mut inner = Pool::get(); - inner.status = status; HttpResponseBuilder { - response: Some(inner), + response: Some(Pool::get(status)), err: None, cookies: None, } @@ -152,10 +67,7 @@ impl HttpResponse { /// Constructs a response #[inline] pub fn new(status: StatusCode, body: Body) -> HttpResponse { - let mut inner = Pool::get(); - inner.status = status; - inner.body = body; - HttpResponse(Some(inner)) + HttpResponse(Some(Pool::with_body(status, body))) } /// Constructs a error response @@ -470,7 +382,7 @@ impl HttpResponseBuilder { } } response.body = body.into(); - Ok(HttpResponse::from_inner(response)) + Ok(HttpResponse(Some(response))) } /// Set a json body and generate `HttpResponse` @@ -495,6 +407,7 @@ impl HttpResponseBuilder { } } +#[inline] #[cfg_attr(feature = "cargo-clippy", allow(borrowed_box))] fn parts<'a>(parts: &'a mut Option>, err: &Option) -> Option<&'a mut Box> @@ -525,6 +438,7 @@ impl Responder for HttpResponseBuilder { type Item = HttpResponse; type Error = HttpError; + #[inline] fn respond_to(mut self, _: HttpRequest) -> Result { self.finish() } @@ -650,6 +564,93 @@ impl Responder for BytesMut { } } +#[derive(Debug)] +struct InnerHttpResponse { + version: Option, + headers: HeaderMap, + status: StatusCode, + reason: Option<&'static str>, + body: Body, + chunked: bool, + encoding: ContentEncoding, + connection_type: Option, + response_size: u64, + error: Option, +} + +impl InnerHttpResponse { + + #[inline] + fn new(status: StatusCode, body: Body) -> InnerHttpResponse { + InnerHttpResponse { + version: None, + headers: HeaderMap::with_capacity(8), + status: status, + reason: None, + body: body, + chunked: false, + encoding: ContentEncoding::Auto, + connection_type: None, + response_size: 0, + error: None, + } + } + +} + +/// Internal use only! unsafe +struct Pool(VecDeque>); + +thread_local!(static POOL: RefCell = RefCell::new(Pool::new())); + +impl Pool { + fn new() -> Pool { + Pool(VecDeque::with_capacity(128)) + } + + fn get(status: StatusCode) -> Box { + POOL.with(|pool| { + if let Some(mut resp) = pool.borrow_mut().0.pop_front() { + resp.body = Body::Empty; + resp.status = status; + resp + } else { + Box::new(InnerHttpResponse::new(status, Body::Empty)) + } + }) + } + + fn with_body(status: StatusCode, body: Body) -> Box { + POOL.with(|pool| { + if let Some(mut resp) = pool.borrow_mut().0.pop_front() { + resp.status = status; + resp.body = Body::Empty; + resp + } else { + Box::new(InnerHttpResponse::new(status, body)) + } + }) + } + + #[cfg_attr(feature = "cargo-clippy", allow(boxed_local))] + fn release(mut inner: Box) { + POOL.with(|pool| { + let v = &mut pool.borrow_mut().0; + if v.len() < 128 { + inner.headers.clear(); + inner.version = None; + inner.chunked = false; + inner.reason = None; + inner.encoding = ContentEncoding::Auto; + inner.connection_type = None; + inner.response_size = 0; + inner.error = None; + v.push_front(inner); + } + }) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/pipeline.rs b/src/pipeline.rs index 91a387534..c04968dc1 100644 --- a/src/pipeline.rs +++ b/src/pipeline.rs @@ -408,19 +408,19 @@ struct WaitingResponse { impl WaitingResponse { + #[inline] fn init(info: &mut PipelineInfo, reply: Reply) -> PipelineState { - let stream = match reply.into() { + match reply.into() { ReplyItem::Message(resp) => - return RunMiddlewares::init(info, resp), + RunMiddlewares::init(info, resp), ReplyItem::Actor(ctx) => - PipelineResponse::Context(ctx), + PipelineState::Handler( + WaitingResponse { stream: PipelineResponse::Context(ctx), _s: PhantomData }), ReplyItem::Future(fut) => - PipelineResponse::Response(fut), - }; - - PipelineState::Handler( - WaitingResponse { stream: stream, _s: PhantomData }) + PipelineState::Handler( + WaitingResponse { stream: PipelineResponse::Response(fut), _s: PhantomData }), + } } fn poll(mut self, info: &mut PipelineInfo) -> Result, PipelineState> { @@ -587,15 +587,6 @@ enum IOState { Done, } -impl IOState { - fn is_done(&self) -> bool { - match *self { - IOState::Done => true, - _ => false - } - } -} - struct DrainVec(Vec>>); impl Drop for DrainVec { @@ -608,6 +599,7 @@ impl Drop for DrainVec { impl ProcessResponse { + #[inline] fn init(resp: HttpResponse) -> PipelineState { PipelineState::Response( @@ -779,11 +771,12 @@ impl ProcessResponse { } // response is completed - if self.iostate.is_done() { - self.resp.set_response_size(io.written()); - Ok(FinishingMiddlewares::init(info, self.resp)) - } else { - Err(PipelineState::Response(self)) + match self.iostate { + IOState::Done => { + self.resp.set_response_size(io.written()); + Ok(FinishingMiddlewares::init(info, self.resp)) + } + _ => Err(PipelineState::Response(self)) } } } @@ -850,6 +843,7 @@ struct Completed(PhantomData); impl Completed { + #[inline] fn init(info: &mut PipelineInfo) -> PipelineState { if info.context.is_none() { PipelineState::None @@ -858,6 +852,7 @@ impl Completed { } } + #[inline] fn poll(self, info: &mut PipelineInfo) -> Result, PipelineState> { match info.poll_context() { Ok(Async::NotReady) => Ok(PipelineState::Completed(Completed(PhantomData))),