-
Notifications
You must be signed in to change notification settings - Fork 281
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
util: add Wrap
#676
base: master
Are you sure you want to change the base?
util: add Wrap
#676
Conversation
This is middleware that wraps a service with both pre and post functions. It offers two flavors, one which is purely for passing shared state from the pre function to the post, and the other of which allows for asynchronous pre/post functions, mapping the request type, and short-circuiting so the inner service isn't called.
More succinctly, this handles the problem of wrapping a service with |
Also tweak nested type signatures on `Pre`/`Post` to use type parameters instead of associated types to simplify the rustdoc output.
The `ServiceExt::wrap` combinator was supposed to let the post function return a different result type than the inner service, but this wasn't properly expressed in the type system.
FWIW I just prototyped an alternative solution that looks like fn service_fn2<T, CallF, PollF>(state: T, poll_ready: PollF, call: CallF) -> ServiceFn2<T, CallF, PollF> { … }
impl<T, CallF, PollF, Fut, Request, R, E> Service<Request> for ServiceFn2<T, CallF, PollF>
where
CallF: FnMut(&mut T, Request) -> Fut,
PollF: FnMut(&mut T, &mut Context<'_>) -> Poll<Result<(), E>>,
Fut: Future<Output = Result<R, E>>,
{ … } and while it's technically doable, we get really awkward errors with the compiler and have to write out type signatures everywhere when using it. I assume this is at least partially due to not being able to specify bounds in the Edit: I suppose producing a generic service with this doesn't work anyway as closures cannot be generic. The I also wrote up an example for Edit 2: Oh right, if we add mutable state then it needs to deal with |
I pushed examples for |
This is middleware that wraps a service with both pre and post functions. It offers two flavors, one which is purely for passing shared state from the pre function to the post, and the other of which allows for asynchronous pre/post functions, mapping the request type, and short-circuiting so the inner service isn't called.
This is something I've wanted for a while, but it took a lot of experimentation to figure out how to actually express this in a way that was both generic and compiled. This is something that I always felt was missing functionality, because it turns out to be fairly common in my experience to want to take some service and wrap it in arbitrary middleware that needs to share state across the call to the inner service.
Some common uses of this are to copy data from the request to the response or to stick a cache in front of a service.
I do think this could probably stand to have some examples added to demonstrate using it, but I didn't want to make the documentation too complex. I'm also open to the idea of flipping the names of
decorate
andwrap
, I just figured thatwrap
was the more obvious name to go for and so that should be the one with simpler usage.