From e903184a125df778908d4395678a6f05ec6e895e Mon Sep 17 00:00:00 2001 From: Luca Palmieri Date: Sat, 29 Jan 2022 16:39:58 +0000 Subject: [PATCH] Update basics/middleware to v4 (#482) Co-authored-by: Rob Ede --- Cargo.lock | 7 ++- basics/middleware/Cargo.toml | 10 ++-- basics/middleware/src/main.rs | 7 +-- basics/middleware/src/read_request_body.rs | 41 +++++++------- basics/middleware/src/read_response_body.rs | 42 +++++++-------- basics/middleware/src/redirect.rs | 60 ++++++++++----------- basics/middleware/src/simple.rs | 32 +++++------ 7 files changed, 89 insertions(+), 110 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f3ad03b..95d5ee71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3569,11 +3569,10 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" name = "middleware-example" version = "2.0.0" dependencies = [ - "actix-service 1.0.6", - "actix-web 3.3.3", - "env_logger 0.8.4", + "actix-web 4.0.0-beta.21", + "env_logger 0.9.0", "futures", - "pin-project 0.4.29", + "pin-project 1.0.10", ] [[package]] diff --git a/basics/middleware/Cargo.toml b/basics/middleware/Cargo.toml index 577c7fde..9273061a 100644 --- a/basics/middleware/Cargo.toml +++ b/basics/middleware/Cargo.toml @@ -5,9 +5,7 @@ authors = ["Gorm Casper ", "Sven-Hendrik Haase Transform for Logging +impl Transform for Logging where - S: Service, Error = Error>, + S: Service, Error = Error>, S::Future: 'static, B: 'static, { - type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; type InitError = (); @@ -25,35 +24,31 @@ where type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { - ok(LoggingMiddleware { - service: Rc::new(RefCell::new(service)), - }) + ready(Ok(LoggingMiddleware { + service: Rc::new(service), + })) } } pub struct LoggingMiddleware { // This is special: We need this to avoid lifetime issues. - service: Rc>, + service: Rc, } -impl Service for LoggingMiddleware +impl Service for LoggingMiddleware where - S: Service, Error = Error> - + 'static, + S: Service, Error = Error> + 'static, S::Future: 'static, B: 'static, { - type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Pin>>>; + type Future = LocalBoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.service.poll_ready(cx) - } + dev::forward_ready!(service); - fn call(&mut self, mut req: ServiceRequest) -> Self::Future { - let mut svc = self.service.clone(); + fn call(&self, mut req: ServiceRequest) -> Self::Future { + let svc = self.service.clone(); Box::pin(async move { let mut body = BytesMut::new(); diff --git a/basics/middleware/src/read_response_body.rs b/basics/middleware/src/read_response_body.rs index b3103418..a2450f49 100644 --- a/basics/middleware/src/read_response_body.rs +++ b/basics/middleware/src/read_response_body.rs @@ -1,22 +1,21 @@ use std::future::Future; +use std::future::{ready, Ready}; use std::marker::PhantomData; use std::pin::Pin; use std::task::{Context, Poll}; -use actix_service::{Service, Transform}; -use actix_web::body::{BodySize, MessageBody, ResponseBody}; +use actix_web::body::{BodySize, MessageBody}; +use actix_web::dev::{self, Service, Transform}; use actix_web::web::{Bytes, BytesMut}; use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error}; -use futures::future::{ok, Ready}; pub struct Logging; -impl Transform for Logging +impl Transform for Logging where - S: Service, Error = Error>, + S: Service, Error = Error>, B: MessageBody + 'static, { - type Request = ServiceRequest; type Response = ServiceResponse>; type Error = Error; type InitError = (); @@ -24,7 +23,7 @@ where type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { - ok(LoggingMiddleware { service }) + ready(Ok(LoggingMiddleware { service })) } } @@ -32,21 +31,18 @@ pub struct LoggingMiddleware { service: S, } -impl Service for LoggingMiddleware +impl Service for LoggingMiddleware where - S: Service, Error = Error>, + S: Service, Error = Error>, B: MessageBody, { - type Request = ServiceRequest; type Response = ServiceResponse>; type Error = Error; type Future = WrapperStream; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.service.poll_ready(cx) - } + dev::forward_ready!(service); - fn call(&mut self, req: ServiceRequest) -> Self::Future { + fn call(&self, req: ServiceRequest) -> Self::Future { WrapperStream { fut: self.service.call(req), _t: PhantomData, @@ -58,7 +54,7 @@ where pub struct WrapperStream where B: MessageBody, - S: Service, + S: Service, { #[pin] fut: S::Future, @@ -68,7 +64,7 @@ where impl Future for WrapperStream where B: MessageBody, - S: Service, Error = Error>, + S: Service, Error = Error>, { type Output = Result>, Error>; @@ -76,11 +72,9 @@ where let res = futures::ready!(self.project().fut.poll(cx)); Poll::Ready(res.map(|res| { - res.map_body(move |_, body| { - ResponseBody::Body(BodyLogger { - body, - body_accum: BytesMut::new(), - }) + res.map_body(move |_, body| BodyLogger { + body, + body_accum: BytesMut::new(), }) })) } @@ -89,7 +83,7 @@ where #[pin_project::pin_project(PinnedDrop)] pub struct BodyLogger { #[pin] - body: ResponseBody, + body: B, body_accum: BytesMut, } @@ -101,6 +95,8 @@ impl PinnedDrop for BodyLogger { } impl MessageBody for BodyLogger { + type Error = B::Error; + fn size(&self) -> BodySize { self.body.size() } @@ -108,7 +104,7 @@ impl MessageBody for BodyLogger { fn poll_next( self: Pin<&mut Self>, cx: &mut Context<'_>, - ) -> Poll>> { + ) -> Poll>> { let this = self.project(); match this.body.poll_next(cx) { diff --git a/basics/middleware/src/redirect.rs b/basics/middleware/src/redirect.rs index bbd56d28..db153a22 100644 --- a/basics/middleware/src/redirect.rs +++ b/basics/middleware/src/redirect.rs @@ -1,65 +1,63 @@ -use std::task::{Context, Poll}; +use std::future::{ready, Ready}; -use actix_service::{Service, Transform}; -use actix_web::dev::{ServiceRequest, ServiceResponse}; +use actix_web::body::EitherBody; +use actix_web::dev::{self, ServiceRequest, ServiceResponse}; +use actix_web::dev::{Service, Transform}; use actix_web::{http, Error, HttpResponse}; -use futures::future::{ok, Either, Ready}; +use futures::future::LocalBoxFuture; pub struct CheckLogin; -impl Transform for CheckLogin +impl Transform for CheckLogin where - S: Service, Error = Error>, + S: Service, Error = Error>, S::Future: 'static, { - type Request = ServiceRequest; - type Response = ServiceResponse; + type Response = ServiceResponse>; type Error = Error; type InitError = (); type Transform = CheckLoginMiddleware; type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { - ok(CheckLoginMiddleware { service }) + ready(Ok(CheckLoginMiddleware { service })) } } pub struct CheckLoginMiddleware { service: S, } -impl Service for CheckLoginMiddleware +impl Service for CheckLoginMiddleware where - S: Service, Error = Error>, + S: Service, Error = Error>, S::Future: 'static, { - type Request = ServiceRequest; - type Response = ServiceResponse; + type Response = ServiceResponse>; type Error = Error; - type Future = Either>>; + type Future = LocalBoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context) -> Poll> { - self.service.poll_ready(cx) - } + dev::forward_ready!(service); - fn call(&mut self, req: ServiceRequest) -> Self::Future { + fn call(&self, req: ServiceRequest) -> Self::Future { // We only need to hook into the `start` for this middleware. - let is_logged_in = false; // Change this to see the change in outcome in the browser + let (request, payload) = req.into_parts(); + let svc_response = self + .service + .call(ServiceRequest::from_parts(request.clone(), payload)); - if is_logged_in { - Either::Left(self.service.call(req)) - } else { + Box::pin(async move { // Don't forward to /login if we are already on /login - if req.path() == "/login" { - Either::Left(self.service.call(req)) + if is_logged_in || request.path() == "/login" { + svc_response.await.map(ServiceResponse::map_into_left_body) } else { - Either::Right(ok(req.into_response( - HttpResponse::Found() - .header(http::header::LOCATION, "/login") - .finish() - .into_body(), - ))) + let response = HttpResponse::Found() + .insert_header((http::header::LOCATION, "/login")) + .finish() + .map_into_right_body(); + + Ok(ServiceResponse::new(request, response)) } - } + }) } } diff --git a/basics/middleware/src/simple.rs b/basics/middleware/src/simple.rs index d9333cc1..e3afe14d 100644 --- a/basics/middleware/src/simple.rs +++ b/basics/middleware/src/simple.rs @@ -1,10 +1,10 @@ -use std::pin::Pin; -use std::task::{Context, Poll}; +use std::future::{ready, Ready}; -use actix_service::{Service, Transform}; -use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error}; -use futures::future::{ok, Ready}; -use futures::Future; +use actix_web::{ + dev::{self, Service, ServiceRequest, ServiceResponse, Transform}, + Error, +}; +use futures::future::LocalBoxFuture; // There are two steps in middleware processing. // 1. Middleware initialization, middleware factory gets called with @@ -15,13 +15,12 @@ pub struct SayHi; // Middleware factory is `Transform` trait from actix-service crate // `S` - type of the next service // `B` - type of response's body -impl Transform for SayHi +impl Transform for SayHi where - S: Service, Error = Error>, + S: Service, Error = Error>, S::Future: 'static, B: 'static, { - type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; type InitError = (); @@ -29,7 +28,7 @@ where type Future = Ready>; fn new_transform(&self, service: S) -> Self::Future { - ok(SayHiMiddleware { service }) + ready(Ok(SayHiMiddleware { service })) } } @@ -37,22 +36,19 @@ pub struct SayHiMiddleware { service: S, } -impl Service for SayHiMiddleware +impl Service for SayHiMiddleware where - S: Service, Error = Error>, + S: Service, Error = Error>, S::Future: 'static, B: 'static, { - type Request = ServiceRequest; type Response = ServiceResponse; type Error = Error; - type Future = Pin>>>; + type Future = LocalBoxFuture<'static, Result>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.service.poll_ready(cx) - } + dev::forward_ready!(service); - fn call(&mut self, req: ServiceRequest) -> Self::Future { + fn call(&self, req: ServiceRequest) -> Self::Future { println!("Hi from start. You requested: {}", req.path()); let fut = self.service.call(req);