http-rs / tide

Fast and friendly HTTP server framework for async Rust
https://docs.rs/tide
Apache License 2.0
5.06k stars 322 forks source link

Work toward cross-framework middleware interface #164

Open aturon opened 5 years ago

aturon commented 5 years ago

Originally posted by @rolftimmermans in https://github.com/rustasync/tide/issues/162#issuecomment-482029031

Having a universal middleware concept in the Rust web-ecosystem is something I look forward to. In the Ruby community, for example, every framework builds on Rack middleware. I see this as the sole factor that allows for (some) code reuse across frameworks.

My questions would be:

aturon commented 5 years ago

If folks want to help on this front, one great step would be to start documenting the various middleware interfaces defined by frameworks today -- Actix, Gotham, Rocket, Tower-Web, Tide. For now, maybe just drop copies of the relevant traits and traits as comments here on this thread.

DoumanAsh commented 5 years ago

Actix's middleware

P.s. personally I think there is no value in trying to work out Middleware since it almost impossible without all other components being shared

secretfader commented 5 years ago

Gotham middleware relies on two traits: Middleware defines the request handler specification, while NewMiddleware creates per-request clones of the middleware implementation.

It isn't terribly complex, but I have questions surrounding how to best wrap RefUnwindSafe.

taqtiqa-mark commented 2 years ago

Sylvain Kerkour has an interesting examination of what the interfaces look like for different exercises, Tide isn't considered but how the exercises look in tide would be interesting (note to self):

https://kerkour.com/rust-web-framework-2022

The "Inventing the Service trait" post shows how Tower's fundamental Service trait could be designed from scratch. @aturon as requested, they end up with something like this (full detail is more involved:

pub trait Service<Request> {
    type Response;
    type Error;
    type Future: Future<Output = Result<Self::Response, Self::Error>>;

    fn poll_ready(
        &mut self,
        cx: &mut Context<'_>,
    ) -> Poll<Result<(), Self::Error>>;

    fn call(&mut self, req: Request) -> Self::Future;
}