Skip to content

Instantly share code, notes, and snippets.

@jplatte
Created October 7, 2020 17:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jplatte/5415a15700dd196cdfa0117f57b12cc4 to your computer and use it in GitHub Desktop.
Save jplatte/5415a15700dd196cdfa0117f57b12cc4 to your computer and use it in GitHub Desktop.
use actix_service::{Service, Transform};
use futures_util::future::{self, FutureExt as _, LocalBoxFuture};
use std::{cell::RefCell, future::Future, rc::Rc};
#[derive(Clone, Debug)]
pub struct Preprocess<F>(pub F);
pub struct PreprocessService<S, F> {
service: Rc<RefCell<S>>,
f: F,
}
impl<S, F, R> Transform<S> for Preprocess<F>
where
S: Service + 'static,
F: FnMut(S::Request) -> R + Clone + 'static,
R: Future<Output = Result<S::Request, S::Error>>,
{
type Request = S::Request;
type Response = S::Response;
type Error = S::Error;
type Transform = PreprocessService<S, F>;
type InitError = ();
type Future = future::Ready<Result<Self::Transform, Self::InitError>>;
fn new_transform(&self, service: S) -> Self::Future {
future::ok(PreprocessService {
service: Rc::new(RefCell::new(service)),
f: self.0.clone(),
})
}
}
impl<S, F, R> Service for PreprocessService<S, F>
where
S: Service + 'static,
F: FnMut(S::Request) -> R + Clone + 'static,
R: Future<Output = Result<S::Request, S::Error>>,
{
type Request = S::Request;
type Response = S::Response;
type Error = S::Error;
type Future = LocalBoxFuture<'static, Result<S::Response, S::Error>>;
fn poll_ready(
&mut self,
ctx: &mut std::task::Context<'_>,
) -> std::task::Poll<Result<(), Self::Error>> {
self.service.borrow_mut().poll_ready(ctx)
}
fn call(&mut self, req: Self::Request) -> Self::Future {
let mut f = self.f.clone();
let service = Rc::clone(&self.service);
async move {
let req = f(req).await?;
let fut = service.borrow_mut().call(req);
fut.await
}
.boxed_local()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment