I create a middleware that checks permissions with Session. so I call into_parts() in ServiceRequest to get HttpRequest and use this to get Session. but there is no way to put them back or create a new ServiceRequest to pass to next middleware.
fn call(&mut self, sreq: ServiceRequest) -> Self::Future {
let (req, _) = sreq.into_parts();
Session::extract(&req).map(|session| {
// ...
})
}
Have you found the answer?
@max-frai not yet.
It is not possible at 1.0.0, It need to provide API to extract it, Maybe something like this (for reference only)
impl Identity {
pub from_service_request(service_request: &ServiceRequest) -> Option<String> {
if let Some(id) = service_request.extensions().get::<IdentityItem>() {
id.id.clone()
} else {
None
}
}
}
We could define trait and provide impl for ServiceRequest and HttpRequest
trait RequestIdentity {
fn get_identity(&mut self) -> Option<String>;
}
impl RequestIdentity for ServiceRequest {...}
Same could be implemented for session.
PR, anyone?
Let me
This will fix only for Identity. What if I want to use my custom extractor for my own structure? So I have something like Worker::from_request(req: &HttpRequest, payload: &mut Payload). It works okay for routes but now I want to get Worker inside middleware. So I should expand ServiceRequest to parts like in first message here, but it will not be possible to pass current ServiceRequest to the next middleware.
Good point, What if we could extract from ServiceRequest
impl ServiceRequest {
// ...
pub fn extract<T>(&self) -> T::Future
where
T: FromRequest,
{
T::extract(&self.0)
}
// ...
}
@nottxy For me it's clear. Let's wait for @fafhrd91. I think this will resolve any such requests.
Using FromRequest with ServiceRequest is not safe. HttpRequest is Clone but ServiceRequest assumes only one ref exists for internal HttpRequest
@fafhrd91 So what's the right way? I think using custom extractors inside middlewares would be common task.
I think right now the way is parsing data by using service_request.headers(), service_request.path(), service_request.query_string(), service_request.cookie(), ..., and save the parsing result to Extensions
@nottxy yes, but existing code in from_request would not be usable here so we should duplicate code?
Maybe move the duplicate code to pure function
code duplication is only option or use extractor instead of middleware.
Extractor works for single route. When I want to work with multiple routes it won't work.
So for example I want to check user has permission to access some route. In my view this should be processed in middlewares which could be applied to group of routes.
Okay, so just reuse from_request logic inside middleware.
Extractor approach is much safer. handler itself states that it requires logged in user. explicit parameter prevent accidental non-protected usage
Most helpful comment
https://docs.rs/actix-session/0.1.1/actix_session/trait.UserSession.html