mirror of
https://github.com/actix/actix-web.git
synced 2025-01-02 05:18:44 +00:00
optimise Extract service (#1841)
This commit is contained in:
parent
a4dbaa8ed1
commit
79de04d862
1 changed files with 47 additions and 63 deletions
110
src/handler.rs
110
src/handler.rs
|
@ -90,26 +90,20 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future {
|
fn call(&mut self, (param, req): (T, HttpRequest)) -> Self::Future {
|
||||||
HandlerServiceResponse {
|
let fut = self.hnd.call(param);
|
||||||
fut: self.hnd.call(param),
|
HandlerServiceResponse::Future(fut, Some(req))
|
||||||
fut2: None,
|
|
||||||
req: Some(req),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
#[pin_project]
|
#[pin_project(project = HandlerProj)]
|
||||||
pub struct HandlerServiceResponse<T, R>
|
pub enum HandlerServiceResponse<T, R>
|
||||||
where
|
where
|
||||||
T: Future<Output = R>,
|
T: Future<Output = R>,
|
||||||
R: Responder,
|
R: Responder,
|
||||||
{
|
{
|
||||||
#[pin]
|
Future(#[pin] T, Option<HttpRequest>),
|
||||||
fut: T,
|
Responder(#[pin] R::Future, Option<HttpRequest>),
|
||||||
#[pin]
|
|
||||||
fut2: Option<R::Future>,
|
|
||||||
req: Option<HttpRequest>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, R> Future for HandlerServiceResponse<T, R>
|
impl<T, R> Future for HandlerServiceResponse<T, R>
|
||||||
|
@ -120,28 +114,26 @@ where
|
||||||
type Output = Result<ServiceResponse, Infallible>;
|
type Output = Result<ServiceResponse, Infallible>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.as_mut().project();
|
loop {
|
||||||
|
match self.as_mut().project() {
|
||||||
if let Some(fut) = this.fut2.as_pin_mut() {
|
HandlerProj::Future(fut, req) => {
|
||||||
return match fut.poll(cx) {
|
let res = ready!(fut.poll(cx));
|
||||||
Poll::Ready(Ok(res)) => {
|
let fut = res.respond_to(req.as_ref().unwrap());
|
||||||
Poll::Ready(Ok(ServiceResponse::new(this.req.take().unwrap(), res)))
|
let state = HandlerServiceResponse::Responder(fut, req.take());
|
||||||
|
self.as_mut().set(state);
|
||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
HandlerProj::Responder(fut, req) => {
|
||||||
Poll::Ready(Err(e)) => {
|
let res = ready!(fut.poll(cx));
|
||||||
let res: Response = e.into().into();
|
let req = req.take().unwrap();
|
||||||
Poll::Ready(Ok(ServiceResponse::new(this.req.take().unwrap(), res)))
|
return match res {
|
||||||
|
Ok(res) => Poll::Ready(Ok(ServiceResponse::new(req, res))),
|
||||||
|
Err(e) => {
|
||||||
|
let res: Response = e.into().into();
|
||||||
|
Poll::Ready(Ok(ServiceResponse::new(req, res)))
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
match this.fut.poll(cx) {
|
|
||||||
Poll::Ready(res) => {
|
|
||||||
let fut = res.respond_to(this.req.as_ref().unwrap());
|
|
||||||
self.as_mut().project().fut2.set(Some(fut));
|
|
||||||
self.poll(cx)
|
|
||||||
}
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,12 +161,12 @@ where
|
||||||
Error = Infallible,
|
Error = Infallible,
|
||||||
> + Clone,
|
> + Clone,
|
||||||
{
|
{
|
||||||
type Config = ();
|
|
||||||
type Request = ServiceRequest;
|
type Request = ServiceRequest;
|
||||||
type Response = ServiceResponse;
|
type Response = ServiceResponse;
|
||||||
type Error = (Error, ServiceRequest);
|
type Error = (Error, ServiceRequest);
|
||||||
type InitError = ();
|
type Config = ();
|
||||||
type Service = ExtractService<T, S>;
|
type Service = ExtractService<T, S>;
|
||||||
|
type InitError = ();
|
||||||
type Future = Ready<Result<Self::Service, ()>>;
|
type Future = Ready<Result<Self::Service, ()>>;
|
||||||
|
|
||||||
fn new_service(&self, _: ()) -> Self::Future {
|
fn new_service(&self, _: ()) -> Self::Future {
|
||||||
|
@ -210,24 +202,14 @@ where
|
||||||
fn call(&mut self, req: ServiceRequest) -> Self::Future {
|
fn call(&mut self, req: ServiceRequest) -> Self::Future {
|
||||||
let (req, mut payload) = req.into_parts();
|
let (req, mut payload) = req.into_parts();
|
||||||
let fut = T::from_request(&req, &mut payload);
|
let fut = T::from_request(&req, &mut payload);
|
||||||
|
ExtractResponse::Future(fut, Some(req), self.service.clone())
|
||||||
ExtractResponse {
|
|
||||||
fut,
|
|
||||||
req,
|
|
||||||
fut_s: None,
|
|
||||||
service: self.service.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project]
|
#[pin_project(project = ExtractProj)]
|
||||||
pub struct ExtractResponse<T: FromRequest, S: Service> {
|
pub enum ExtractResponse<T: FromRequest, S: Service> {
|
||||||
req: HttpRequest,
|
Future(#[pin] T::Future, Option<HttpRequest>, S),
|
||||||
service: S,
|
Response(#[pin] S::Future),
|
||||||
#[pin]
|
|
||||||
fut: T::Future,
|
|
||||||
#[pin]
|
|
||||||
fut_s: Option<S::Future>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromRequest, S> Future for ExtractResponse<T, S>
|
impl<T: FromRequest, S> Future for ExtractResponse<T, S>
|
||||||
|
@ -241,21 +223,23 @@ where
|
||||||
type Output = Result<ServiceResponse, (Error, ServiceRequest)>;
|
type Output = Result<ServiceResponse, (Error, ServiceRequest)>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let this = self.as_mut().project();
|
loop {
|
||||||
|
match self.as_mut().project() {
|
||||||
if let Some(fut) = this.fut_s.as_pin_mut() {
|
ExtractProj::Future(fut, req, srv) => {
|
||||||
return fut.poll(cx).map_err(|_| panic!());
|
let res = ready!(fut.poll(cx));
|
||||||
}
|
let req = req.take().unwrap();
|
||||||
|
match res {
|
||||||
match ready!(this.fut.poll(cx)) {
|
Err(e) => {
|
||||||
Err(e) => {
|
let req = ServiceRequest::new(req);
|
||||||
let req = ServiceRequest::new(this.req.clone());
|
return Poll::Ready(Err((e.into(), req)));
|
||||||
Poll::Ready(Err((e.into(), req)))
|
}
|
||||||
}
|
Ok(item) => {
|
||||||
Ok(item) => {
|
let fut = srv.call((item, req));
|
||||||
let fut = Some(this.service.call((item, this.req.clone())));
|
self.as_mut().set(ExtractResponse::Response(fut));
|
||||||
self.as_mut().project().fut_s.set(fut);
|
}
|
||||||
self.poll(cx)
|
}
|
||||||
|
}
|
||||||
|
ExtractProj::Response(fut) => return fut.poll(cx).map_err(|_| panic!()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue