Allow access to request when rendering errors
- Lenguaje dominante
- Rust
- Estrellas
- 24.8k
- Forks
- 1.9k
- Merge medio
- 23 h 10 min
- PR fusionados (30 d)
- 26
Descripción
This was requested a few times already (the most recent one I found is #1159) but I want to elaborate a little more on this issue. I started using actix-web for web-development and plan to use it for production purposes. I wrote a project that uses actix-web and a template engine to render HTML pages. This means that I also want to render errors as HTML pages using the template engine, therefore I need access to the request for various things in the application state, including the templates.
I thought of various ways to implement this:
1. Implement `ResponseError` on an error type and render the error in `ResponseError::error_response`. This would be the most ergonomic approach by far if the method received a `HttpRequest`, which it does not.
2. Include the `HttpRequest` in the error type and then implement 1. This method works, but results in a lot of `map_err`s in the handler functions, making this approach more unergonomic.
3. "Improve" 2. by writing a function `f_inner` for each handler function `f`, that returns an immediate error type (without the request) and only call `map_err` once in `f` to map to the full error type (with the request). While this reduces the amount of `map_err`s, it duplicates a lot of handler functions signatures (and in my opinion, mixing 2 and 3 makes the code inconsistent and even more unreadable). (This whole approach could be improved with try-block syntax, which is not stable yet)
4. Writing a middleware that checks for an error and renders the template. This approach is even less idiomatic than the ones above because it potentially requires downcasting the error type for getting the original error type and requires much more insight into the actix-web library than the other approaches. Trying out this method I also had some issues with logging, e.g. that errors were not logged anymore or that the wrong status code was logged.
In my opinion, not being able to implement the first approach does not only harm the ergonomics of the code, it also might discourage people (especially more inexperienced Rust developers) because finding a good alternative to 1. seems unintuitive right now.
Of course changing the method signature, as suggested in previous issues, breaks the API and seemingly causes a few more complications. I think a better approach would be something like: allow handlers to return a `Result` where `T` and `E` both implement `Responder` (which is also the approach used in the web-frameworks rocket and axum).
While I don't know whether this can be included in a non-breaking way, I still think it's worth to consider, maybe even for a breaking change going into actix v5.
Guía de contribución
Evaluación
Este issue todavía no se ha evaluado.