sparckles / Robyn

Robyn is a Super Fast Async Python Web Framework with a Rust runtime.
https://robyn.tech/
BSD 2-Clause "Simplified" License
4.45k stars 230 forks source link

implement middleware chains #828

Open sansyrox opened 5 months ago

sansyrox commented 5 months ago

def fx1():
   ...

def fx2():
  ...

mc = MiddlewareChain(fx1, fx2)

app.before_request("/route", mc)
ashupednekar commented 1 month ago

@sansyrox Is someone working on this? If not, I'd like to take this up.

Middleware chains are essential for making Robyn more suitable for mainstream production scenarios

ashupednekar commented 1 month ago

As I understand, rn the limitation stems from

        table.write().unwrap().insert(route.to_string(), function)?;

where the matchit router map for "before/after" request type allows for only one key and panics on duplicate registration.

That's the case of route middlewares, but is handled in case of global middlewares which has a Vec<FunctionInfo>, right?

    for before_middleware in before_middlewares {
        request = match execute_middleware_function(&request, &before_middleware).await {
            Ok(MiddlewareReturn::Request(r)) => r,
            Ok(MiddlewareReturn::Response(r)) => {
                // If a before middleware returns a response, we abort the request and return the response
                return r;
            }
            Err(e) => {
                error!(
                    "Error while executing before middleware function for endpoint `{}`: {}",
                    req.uri().path(),
                    get_traceback(e.downcast_ref::<PyErr>().unwrap())
                );
                return Response::internal_server_error(None);
            }
        };
    }

Speaking of which, I couldn't find documentation on how to add global middlewares from python... the add_global_middleware function is not yet exposed to python, is that it? Sry if I missed sth in the docs xP