Closed pfrenssen closed 4 years ago
I found that this minimal example does work, this will find the TEST
string in the .app_data()
passed from within an error handler.
use actix_http::{body::Body, Response};
use actix_web::dev::ServiceResponse;
use actix_web::http::StatusCode;
use actix_web::middleware::errhandlers::{ErrorHandlerResponse, ErrorHandlers};
use actix_web::{web::Data, App, HttpServer, Result};
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new()
.data("TEST".to_string())
.wrap(error_handlers()))
.bind("127.0.0.1:8088")?
.run()
.await
}
pub fn error_handlers() -> ErrorHandlers<Body> {
ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)
}
fn not_found<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<B>> {
let request = res.request();
let content = request.app_data::<Data<String>>().unwrap().get_ref();
let response = Response::build(res.status()).body(content);
Ok(ErrorHandlerResponse::Response(
res.into_response(response.into_body()),
))
}
I will narrow down the problem to see what causes the data to be missing in my example in the summary. It might be due to the data being registered inside web::scope()
as was suggested on gitter.
I found it, it is indeed due to web::scope()
.
Moving the app configuration into a second method, and wrapping the .data()
call into .scope("")
makes the value inaccessible. Replacing main()
with the following causes the data to be inaccessible:
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| App::new().configure(|c| conf(c)))
.bind("127.0.0.1:8088")?
.run()
.await
}
fn conf(c: &mut ServiceConfig) {
c.service(scope("")
.data("TEST".to_string()) // <<<< Data inside `scope()` is inaccessible
.wrap(error_handlers()));
}
This small change makes the data accessible again:
fn conf(c: &mut ServiceConfig) {
c.data("TEST".to_string())
.service(scope("").wrap(error_handlers()));
}
want to find out if this is a bug or not
Found the culprit. The usage of the error middleware was a red herring here.
The problem is an already fixed issue whereby default services are not given current-level data. Fixed here: #1452.
If you try your code using actix-web v3 alpha you'll find it works.
I would like to render my error pages in HTML format using Tera templates. The Tera engine is added to my application using app_data (ref. full code at https://github.com/pfrenssen/firetrack/blob/a500519748aa1e3ad52ecf9fff832d127df8ce27/web/src/lib.rs#L73).
I have an error handler defined as such:
I seem to be unable to access the app_data in the error handler. When I access a 404 page I see the following log output:
Moreover, it seems that the app data is completely empty, if I hack the following debugging info in
extensions.rs
then it appears that theExtensions
are empty:This results in the following log output, which seems to indicate that none of my 3 registered extensions are available here:
Is there a way that we can currently access the app_data in an error handler, or if this needs to be implemented, where should this be done?