Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add axum-handle-error-extract crate #468

Merged
merged 5 commits into from
Nov 8, 2021
Merged

Conversation

davidpdrsn
Copy link
Member

For a project I'm working on with axum I have a "application renderer" extractor thing that takes HTML templates and renders those with a standard application layout around it. It needs to be an extractor because it grabs data from the session to show in the layout like whether the user is logged in or not.

However I couldn't easily use this same setup for handling errors from middleware since HandleErrorLayer doesn't support running extractors. I think that is something that makes sense to support. If you don't need to run any extractors you just don't specify any and things work like they did before.

I also think it makes sense to support async functions for handling errors in case users wanna do some async logging or whatnot while handling the error.

So this PR introduces a new crate called axum-handle-error-extract which has its own HandleErrorLayer that supports extractors and async functions.

For axum 0.4 I'm thinking we should replace the current HandleErrorLayer with this new more powerful version. Thats of course a breaking change but figured we could at least release it as a standalone crate so users can try it. Pretty neat that axum is flexible enough to support something like this 😊

Example usage

use axum::{
    Router,
    BoxError,
    response::IntoResponse,
    http::{StatusCode, Method, Uri},
    routing::get,
};
use tower::{ServiceBuilder, timeout::error::Elapsed};
use std::time::Duration;
use axum_handle_error_extract::HandleErrorLayer;

let app = Router::new()
    .route("/", get(|| async {}))
    .layer(
        ServiceBuilder::new()
            // timeouts produces errors, so we handle those with `handle_error`
            .layer(HandleErrorLayer::new(handle_error))
            .timeout(Duration::from_secs(10))
    );

// our handler take can 0 to 16 extractors and the final argument must
// always be the error produced by the middleware
async fn handle_error(
    method: Method,
    uri: Uri,
    error: BoxError,
) -> impl IntoResponse {
    if error.is::<Elapsed>() {
        (
            StatusCode::REQUEST_TIMEOUT,
            format!("{} {} took too long", method, uri),
        )
    } else {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("{} {} failed: {}", method, uri, error),
        )
    }
}

@davidpdrsn davidpdrsn requested a review from jplatte November 5, 2021 17:24
axum-handle-error-extract/Cargo.toml Show resolved Hide resolved
axum-handle-error-extract/src/lib.rs Show resolved Hide resolved
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("HandleError")
.field("inner", &self.inner)
.field("f", &format_args!("{}", std::any::type_name::<F>()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't &type_name(), w/o the format_args!, work too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think thats right! No idea why we wrote it like this in tower. Seems to do the same.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I know now actually 😅

W/o format_args it will add quotes, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah thats true. I'll revert to keep the format_args.

@davidpdrsn
Copy link
Member Author

I think I'll go ahead and merge this now. We can always improve things later as we add more crates and use this in practice.

@davidpdrsn davidpdrsn merged commit 7e40312 into main Nov 8, 2021
@davidpdrsn davidpdrsn deleted the handle-error-extractr branch November 8, 2021 18:24
@davidpdrsn davidpdrsn mentioned this pull request Nov 8, 2021
1 task
EdorianDark pushed a commit to EdorianDark/axum that referenced this pull request Nov 24, 2021
* Add `axum-handle-error-extract` crate

* fixup

* Fix readme link

* Add `HandleErrorExt` for new error handling middleware

* Revert "fixup"

This reverts commit 83e0495.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants