How can I pass structs from an Actix middleware to the handler?
Asked Answered
A

1

7

I'm trying to write an authentication middleware for my Actix application. When validating the request in the middleware, I make a call to a database to retrieve the necessary user data to validate the incoming request. Once the request has been authorised, I want to be able to pass this user data to the handler as this will allow me to avoid having the query for the same data twice.

I can't find a solution for this. The best suggestion I could find so far was to "set a request extension". There doesn't seem to be any examples for this and there is also too little documentation around this to work out what to do here.

Apulia answered 31/8, 2020 at 15:12 Comment(2)
Have you seen https://mcmap.net/q/415790/-how-can-i-make-protected-routes-in-actix-web Or even more comple web.archive.org/web/20200811175006if_/https://github.com/…Limicolous
Does this answer your question? How can I make protected routes in actix-webRibbonwood
E
12

You can pass data from middleware (service) to handler via extensions.

First of all you have to insert extension (in service). The HttpMessage trait is implemented for ServiceRequest struct and provides extensions_mut() function. It must be mutable because you will be inserting new extension.

It might look something like this:

req.extensions_mut().insert(user);

Then you have to implement FromRequest trait for your data structure.

impl FromRequest for User {
    type Error = actix_web::Error;
    type Future = futures::future::Ready<Result<Self, Self::Error>>;
    type Config = ();

    fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {
        match req.extensions().get::<User>() {
            Some(user) => return ok(user.clone()),
            None => return err(actix_web::error::ErrorBadRequest("ups..."))
        };
    }

}

Then you're ready to use it in handler.

pub async fn get_user_handler(user: User) {}
Etsukoetta answered 24/6, 2021 at 11:0 Comment(3)
really nice answer, thanks! It is worth to mention that User must have derived CloneAmal
As of actix-web 3.2.0, there is the ReqData extractor. So you can use a ReqData<User> parameter in your handler instead of implementing FromRequest for User.Electrometallurgy
Note that the ok and err types come from the "futures" crate on crates.io. Not shown in the example is use futures::future::{ok, err};Mascle

© 2022 - 2024 — McMap. All rights reserved.