mirror of
https://github.com/actix/examples
synced 2024-11-23 22:41:07 +01:00
Update basics/middleware to v4 (#482)
Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
parent
9a00813b93
commit
e903184a12
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -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]]
|
||||
|
@ -5,9 +5,7 @@ authors = ["Gorm Casper <gcasper@gmail.com>", "Sven-Hendrik Haase <svenstaro@gma
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-service = "1"
|
||||
actix-web = "3"
|
||||
|
||||
env_logger = "0.8"
|
||||
futures = "0.3.1"
|
||||
pin-project = "0.4"
|
||||
actix-web = "4.0.0-beta.21"
|
||||
env_logger = "0.9"
|
||||
futures = "0.3.7"
|
||||
pin-project = "1"
|
||||
|
@ -1,8 +1,5 @@
|
||||
#![allow(clippy::type_complexity)]
|
||||
|
||||
use actix_service::Service;
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use futures::future::FutureExt;
|
||||
use actix_web::{dev::Service, web, App, HttpServer};
|
||||
use futures::FutureExt as _;
|
||||
|
||||
#[allow(dead_code)]
|
||||
mod read_request_body;
|
||||
|
@ -1,23 +1,22 @@
|
||||
use std::cell::RefCell;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::task::{Context, Poll};
|
||||
use std::{
|
||||
future::{ready, Ready},
|
||||
rc::Rc,
|
||||
};
|
||||
|
||||
use actix_service::{Service, Transform};
|
||||
use actix_web::dev::{self, Service, Transform};
|
||||
use actix_web::web::BytesMut;
|
||||
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error, HttpMessage};
|
||||
use futures::future::{ok, Future, Ready};
|
||||
use futures::future::LocalBoxFuture;
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
pub struct Logging;
|
||||
|
||||
impl<S: 'static, B> Transform<S> for Logging
|
||||
impl<S: 'static, B> Transform<S, ServiceRequest> for Logging
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
@ -25,35 +24,31 @@ where
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
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<S> {
|
||||
// This is special: We need this to avoid lifetime issues.
|
||||
service: Rc<RefCell<S>>,
|
||||
service: Rc<S>,
|
||||
}
|
||||
|
||||
impl<S, B> Service for LoggingMiddleware<S>
|
||||
impl<S, B> Service<ServiceRequest> for LoggingMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>
|
||||
+ 'static,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
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();
|
||||
|
@ -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<S: 'static, B> Transform<S> for Logging
|
||||
impl<S: 'static, B> Transform<S, ServiceRequest> for Logging
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
B: MessageBody + 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<BodyLogger<B>>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
@ -24,7 +23,7 @@ where
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(LoggingMiddleware { service })
|
||||
ready(Ok(LoggingMiddleware { service }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,21 +31,18 @@ pub struct LoggingMiddleware<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for LoggingMiddleware<S>
|
||||
impl<S, B> Service<ServiceRequest> for LoggingMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
B: MessageBody,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<BodyLogger<B>>;
|
||||
type Error = Error;
|
||||
type Future = WrapperStream<S, B>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
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<S, B>
|
||||
where
|
||||
B: MessageBody,
|
||||
S: Service,
|
||||
S: Service<ServiceRequest>,
|
||||
{
|
||||
#[pin]
|
||||
fut: S::Future,
|
||||
@ -68,7 +64,7 @@ where
|
||||
impl<S, B> Future for WrapperStream<S, B>
|
||||
where
|
||||
B: MessageBody,
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
{
|
||||
type Output = Result<ServiceResponse<BodyLogger<B>>, 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<B> {
|
||||
#[pin]
|
||||
body: ResponseBody<B>,
|
||||
body: B,
|
||||
body_accum: BytesMut,
|
||||
}
|
||||
|
||||
@ -101,6 +95,8 @@ impl<B> PinnedDrop for BodyLogger<B> {
|
||||
}
|
||||
|
||||
impl<B: MessageBody> MessageBody for BodyLogger<B> {
|
||||
type Error = B::Error;
|
||||
|
||||
fn size(&self) -> BodySize {
|
||||
self.body.size()
|
||||
}
|
||||
@ -108,7 +104,7 @@ impl<B: MessageBody> MessageBody for BodyLogger<B> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Result<Bytes, Error>>> {
|
||||
) -> Poll<Option<Result<Bytes, Self::Error>>> {
|
||||
let this = self.project();
|
||||
|
||||
match this.body.poll_next(cx) {
|
||||
|
@ -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<S, B> Transform<S> for CheckLogin
|
||||
impl<S, B> Transform<S, ServiceRequest> for CheckLogin
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Response = ServiceResponse<EitherBody<B>>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
type Transform = CheckLoginMiddleware<S>;
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(CheckLoginMiddleware { service })
|
||||
ready(Ok(CheckLoginMiddleware { service }))
|
||||
}
|
||||
}
|
||||
pub struct CheckLoginMiddleware<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for CheckLoginMiddleware<S>
|
||||
impl<S, B> Service<ServiceRequest> for CheckLoginMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Response = ServiceResponse<EitherBody<B>>;
|
||||
type Error = Error;
|
||||
type Future = Either<S::Future, Ready<Result<Self::Response, Self::Error>>>;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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<S, B> Transform<S> for SayHi
|
||||
impl<S, B> Transform<S, ServiceRequest> for SayHi
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type InitError = ();
|
||||
@ -29,7 +28,7 @@ where
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(SayHiMiddleware { service })
|
||||
ready(Ok(SayHiMiddleware { service }))
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,22 +36,19 @@ pub struct SayHiMiddleware<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for SayHiMiddleware<S>
|
||||
impl<S, B> Service<ServiceRequest> for SayHiMiddleware<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
B: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = Error;
|
||||
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user