mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-24 16:02:59 +01:00
cleanup response
This commit is contained in:
parent
a8b2f1b821
commit
1daf50095a
@ -110,6 +110,7 @@ impl Responder for HttpResponse {
|
|||||||
type Item = Reply;
|
type Item = Reply;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
Ok(Reply(ReplyItem::Message(self)))
|
Ok(Reply(ReplyItem::Message(self)))
|
||||||
}
|
}
|
||||||
@ -117,6 +118,7 @@ impl Responder for HttpResponse {
|
|||||||
|
|
||||||
impl From<HttpResponse> for Reply {
|
impl From<HttpResponse> for Reply {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn from(resp: HttpResponse) -> Reply {
|
fn from(resp: HttpResponse) -> Reply {
|
||||||
Reply(ReplyItem::Message(resp))
|
Reply(ReplyItem::Message(resp))
|
||||||
}
|
}
|
||||||
@ -152,6 +154,7 @@ impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> Responder for HttpContext<
|
|||||||
type Item = Reply;
|
type Item = Reply;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
Ok(Reply(ReplyItem::Actor(Box::new(self))))
|
Ok(Reply(ReplyItem::Actor(Box::new(self))))
|
||||||
}
|
}
|
||||||
@ -159,6 +162,7 @@ impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> Responder for HttpContext<
|
|||||||
|
|
||||||
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> for Reply {
|
impl<A: Actor<Context=HttpContext<A, S>>, S: 'static> From<HttpContext<A, S>> for Reply {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn from(ctx: HttpContext<A, S>) -> Reply {
|
fn from(ctx: HttpContext<A, S>) -> Reply {
|
||||||
Reply(ReplyItem::Actor(Box::new(ctx)))
|
Reply(ReplyItem::Actor(Box::new(ctx)))
|
||||||
}
|
}
|
||||||
@ -169,6 +173,7 @@ impl Responder for Box<Future<Item=HttpResponse, Error=Error>>
|
|||||||
type Item = Reply;
|
type Item = Reply;
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
fn respond_to(self, _: HttpRequest) -> Result<Reply, Error> {
|
||||||
Ok(Reply(ReplyItem::Future(self)))
|
Ok(Reply(ReplyItem::Future(self)))
|
||||||
}
|
}
|
||||||
|
@ -29,86 +29,6 @@ pub enum ConnectionType {
|
|||||||
Upgrade,
|
Upgrade,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
struct InnerHttpResponse {
|
|
||||||
version: Option<Version>,
|
|
||||||
headers: HeaderMap,
|
|
||||||
status: StatusCode,
|
|
||||||
reason: Option<&'static str>,
|
|
||||||
body: Body,
|
|
||||||
chunked: bool,
|
|
||||||
encoding: ContentEncoding,
|
|
||||||
connection_type: Option<ConnectionType>,
|
|
||||||
response_size: u64,
|
|
||||||
error: Option<Error>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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<Box<InnerHttpResponse>>);
|
|
||||||
|
|
||||||
thread_local!(static POOL: RefCell<Pool> = RefCell::new(Pool::new()));
|
|
||||||
|
|
||||||
impl Pool {
|
|
||||||
fn new() -> Pool {
|
|
||||||
Pool(VecDeque::with_capacity(128))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get() -> Box<InnerHttpResponse> {
|
|
||||||
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<InnerHttpResponse>) {
|
|
||||||
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
|
/// An HTTP Response
|
||||||
pub struct HttpResponse(Option<Box<InnerHttpResponse>>);
|
pub struct HttpResponse(Option<Box<InnerHttpResponse>>);
|
||||||
|
|
||||||
@ -123,27 +43,22 @@ impl Drop for HttpResponse {
|
|||||||
impl HttpResponse {
|
impl HttpResponse {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[cfg_attr(feature = "cargo-clippy", allow(inline_always))]
|
||||||
fn get_ref(&self) -> &InnerHttpResponse {
|
fn get_ref(&self) -> &InnerHttpResponse {
|
||||||
self.0.as_ref().unwrap()
|
self.0.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[cfg_attr(feature = "cargo-clippy", allow(inline_always))]
|
||||||
fn get_mut(&mut self) -> &mut InnerHttpResponse {
|
fn get_mut(&mut self) -> &mut InnerHttpResponse {
|
||||||
self.0.as_mut().unwrap()
|
self.0.as_mut().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_inner(inner: Box<InnerHttpResponse>) -> HttpResponse {
|
|
||||||
HttpResponse(Some(inner))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create http response builder with specific status.
|
/// Create http response builder with specific status.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn build(status: StatusCode) -> HttpResponseBuilder {
|
pub fn build(status: StatusCode) -> HttpResponseBuilder {
|
||||||
let mut inner = Pool::get();
|
|
||||||
inner.status = status;
|
|
||||||
HttpResponseBuilder {
|
HttpResponseBuilder {
|
||||||
response: Some(inner),
|
response: Some(Pool::get(status)),
|
||||||
err: None,
|
err: None,
|
||||||
cookies: None,
|
cookies: None,
|
||||||
}
|
}
|
||||||
@ -152,10 +67,7 @@ impl HttpResponse {
|
|||||||
/// Constructs a response
|
/// Constructs a response
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(status: StatusCode, body: Body) -> HttpResponse {
|
pub fn new(status: StatusCode, body: Body) -> HttpResponse {
|
||||||
let mut inner = Pool::get();
|
HttpResponse(Some(Pool::with_body(status, body)))
|
||||||
inner.status = status;
|
|
||||||
inner.body = body;
|
|
||||||
HttpResponse(Some(inner))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a error response
|
/// Constructs a error response
|
||||||
@ -470,7 +382,7 @@ impl HttpResponseBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
response.body = body.into();
|
response.body = body.into();
|
||||||
Ok(HttpResponse::from_inner(response))
|
Ok(HttpResponse(Some(response)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a json body and generate `HttpResponse`
|
/// Set a json body and generate `HttpResponse`
|
||||||
@ -495,6 +407,7 @@ impl HttpResponseBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(borrowed_box))]
|
#[cfg_attr(feature = "cargo-clippy", allow(borrowed_box))]
|
||||||
fn parts<'a>(parts: &'a mut Option<Box<InnerHttpResponse>>, err: &Option<HttpError>)
|
fn parts<'a>(parts: &'a mut Option<Box<InnerHttpResponse>>, err: &Option<HttpError>)
|
||||||
-> Option<&'a mut Box<InnerHttpResponse>>
|
-> Option<&'a mut Box<InnerHttpResponse>>
|
||||||
@ -525,6 +438,7 @@ impl Responder for HttpResponseBuilder {
|
|||||||
type Item = HttpResponse;
|
type Item = HttpResponse;
|
||||||
type Error = HttpError;
|
type Error = HttpError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn respond_to(mut self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
fn respond_to(mut self, _: HttpRequest) -> Result<HttpResponse, HttpError> {
|
||||||
self.finish()
|
self.finish()
|
||||||
}
|
}
|
||||||
@ -650,6 +564,93 @@ impl Responder for BytesMut {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct InnerHttpResponse {
|
||||||
|
version: Option<Version>,
|
||||||
|
headers: HeaderMap,
|
||||||
|
status: StatusCode,
|
||||||
|
reason: Option<&'static str>,
|
||||||
|
body: Body,
|
||||||
|
chunked: bool,
|
||||||
|
encoding: ContentEncoding,
|
||||||
|
connection_type: Option<ConnectionType>,
|
||||||
|
response_size: u64,
|
||||||
|
error: Option<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Box<InnerHttpResponse>>);
|
||||||
|
|
||||||
|
thread_local!(static POOL: RefCell<Pool> = RefCell::new(Pool::new()));
|
||||||
|
|
||||||
|
impl Pool {
|
||||||
|
fn new() -> Pool {
|
||||||
|
Pool(VecDeque::with_capacity(128))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get(status: StatusCode) -> Box<InnerHttpResponse> {
|
||||||
|
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<InnerHttpResponse> {
|
||||||
|
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<InnerHttpResponse>) {
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -408,19 +408,19 @@ struct WaitingResponse<S> {
|
|||||||
|
|
||||||
impl<S> WaitingResponse<S> {
|
impl<S> WaitingResponse<S> {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn init(info: &mut PipelineInfo<S>, reply: Reply) -> PipelineState<S>
|
fn init(info: &mut PipelineInfo<S>, reply: Reply) -> PipelineState<S>
|
||||||
{
|
{
|
||||||
let stream = match reply.into() {
|
match reply.into() {
|
||||||
ReplyItem::Message(resp) =>
|
ReplyItem::Message(resp) =>
|
||||||
return RunMiddlewares::init(info, resp),
|
RunMiddlewares::init(info, resp),
|
||||||
ReplyItem::Actor(ctx) =>
|
ReplyItem::Actor(ctx) =>
|
||||||
PipelineResponse::Context(ctx),
|
|
||||||
ReplyItem::Future(fut) =>
|
|
||||||
PipelineResponse::Response(fut),
|
|
||||||
};
|
|
||||||
|
|
||||||
PipelineState::Handler(
|
PipelineState::Handler(
|
||||||
WaitingResponse { stream: stream, _s: PhantomData })
|
WaitingResponse { stream: PipelineResponse::Context(ctx), _s: PhantomData }),
|
||||||
|
ReplyItem::Future(fut) =>
|
||||||
|
PipelineState::Handler(
|
||||||
|
WaitingResponse { stream: PipelineResponse::Response(fut), _s: PhantomData }),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S>, PipelineState<S>> {
|
fn poll(mut self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S>, PipelineState<S>> {
|
||||||
@ -587,15 +587,6 @@ enum IOState {
|
|||||||
Done,
|
Done,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IOState {
|
|
||||||
fn is_done(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
IOState::Done => true,
|
|
||||||
_ => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct DrainVec(Vec<Rc<RefCell<DrainFut>>>);
|
struct DrainVec(Vec<Rc<RefCell<DrainFut>>>);
|
||||||
|
|
||||||
impl Drop for DrainVec {
|
impl Drop for DrainVec {
|
||||||
@ -608,6 +599,7 @@ impl Drop for DrainVec {
|
|||||||
|
|
||||||
impl<S> ProcessResponse<S> {
|
impl<S> ProcessResponse<S> {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn init(resp: HttpResponse) -> PipelineState<S>
|
fn init(resp: HttpResponse) -> PipelineState<S>
|
||||||
{
|
{
|
||||||
PipelineState::Response(
|
PipelineState::Response(
|
||||||
@ -779,11 +771,12 @@ impl<S> ProcessResponse<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// response is completed
|
// response is completed
|
||||||
if self.iostate.is_done() {
|
match self.iostate {
|
||||||
|
IOState::Done => {
|
||||||
self.resp.set_response_size(io.written());
|
self.resp.set_response_size(io.written());
|
||||||
Ok(FinishingMiddlewares::init(info, self.resp))
|
Ok(FinishingMiddlewares::init(info, self.resp))
|
||||||
} else {
|
}
|
||||||
Err(PipelineState::Response(self))
|
_ => Err(PipelineState::Response(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -850,6 +843,7 @@ struct Completed<S>(PhantomData<S>);
|
|||||||
|
|
||||||
impl<S> Completed<S> {
|
impl<S> Completed<S> {
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn init(info: &mut PipelineInfo<S>) -> PipelineState<S> {
|
fn init(info: &mut PipelineInfo<S>) -> PipelineState<S> {
|
||||||
if info.context.is_none() {
|
if info.context.is_none() {
|
||||||
PipelineState::None
|
PipelineState::None
|
||||||
@ -858,6 +852,7 @@ impl<S> Completed<S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn poll(self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S>, PipelineState<S>> {
|
fn poll(self, info: &mut PipelineInfo<S>) -> Result<PipelineState<S>, PipelineState<S>> {
|
||||||
match info.poll_context() {
|
match info.poll_context() {
|
||||||
Ok(Async::NotReady) => Ok(PipelineState::Completed(Completed(PhantomData))),
|
Ok(Async::NotReady) => Ok(PipelineState::Completed(Completed(PhantomData))),
|
||||||
|
Loading…
Reference in New Issue
Block a user