Repository navigation
Replies: 1 comment
|
If the old body is intentionally discarded, change the associated response type in both the use actix_web::body::{BoxBody, MessageBody};
impl<S, B> Service<ServiceRequest> for LayoutMiddlewareService<S>
where
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: MessageBody + 'static,
{
type Response = ServiceResponse<BoxBody>;
type Error = Error;
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
// ...
fn call(&self, req: ServiceRequest) -> Self::Future {
let layout = Rc::new(RefCell::new(Layout::default()));
req.extensions_mut().insert(layout);
let future = self.service.call(req);
Box::pin(async move {
let response = future.await?;
let layout = response
.request()
.extensions()
.get::<Rc<RefCell<Layout>>>()
.expect("Layout not inserted by middleware")
.clone();
let rendered = render_mustache_template(&layout.borrow())?;
Ok(response
.map_body(|_, _old_body| rendered)
.map_into_boxed_body())
})
}
}If you need the handler's previous body inside the layout, The request-extension approach can work, but for HTML-only handlers a typed page/view model rendered by a shared layout helper is usually simpler. Middleware has to erase or buffer arbitrary response bodies and also decide what to do with redirects, errors, streams, and non-HTML responses. |
Uh oh!
There was an error while loading. Please reload this page.
Hi!
I'm using actix to render html pages and I am currently trying to share the same base template across pages (especially for head tag)
So I have 2 structures: Layout and LayoutExtractor. The first holds data and the second only contains a
Rc<RefCell<Layout>>. Then LayoutExtractor implements FromRequest to get the layout from request extensions:Then I have 2 other structures for a middleware. LayoutMiddleware with exactly the same Transform implementation of the doc and LayoutMiddlewareService implementing Service. For this one I first add the Layout in request extensions, then call the service. And the hell comes just after: I retrieve the layout from the service response and use it to render my mustache template. Until this point all is good (almost). My problem is just after, I want to replace the response body with my newly rendered one, so I use map_body but I get a compilation error ->
expected 'Result<ServiceResponse<B>, Error>', found 'Result<ServiceResponse<String>, _>'(ideally I will also want to pass the previous body to my renderer in order to include it)I have searched for discussion here, on stack-overflow and asked AI but found no viable answer. Am I totally wrong on my architecture?
The handler looks like this:
All reactions