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

Support chaining handlers with one.or(two).or(three) #1170

Merged
merged 6 commits into from
Aug 10, 2022
Merged

Conversation

davidpdrsn
Copy link
Member

This is something I've playing around with which I think we should explore in axum-extra. It enables doing handler fallbacks like this:

async fn one(Path(id): Path<u32>) -> String {
    id.to_string()
}

async fn two(Query(params): Query<Params>) -> String {
    params.a
}

async fn three() -> &'static str {
    "fallback"
}

let handler = one.or(two).or(three);
let app = Router::new().route("/:id", get(handler));

So if one rejects then two runs and finally three.

This is something users have asked about for but our current best solution is "do it manually in a single handler". That is quite tedious especially if you want to run different extractors for each handler.

@davidpdrsn davidpdrsn added this to the 0.6 milestone Jul 17, 2022
@davidpdrsn davidpdrsn changed the title Add handler trait that supports fallbacks Support chaining handlers with one.or(two).or(three) Jul 26, 2022
@davidpdrsn davidpdrsn marked this pull request as ready for review July 26, 2022 11:54
@davidpdrsn davidpdrsn requested a review from jplatte July 26, 2022 11:54
Copy link
Member

@jplatte jplatte left a comment

Choose a reason for hiding this comment

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

An interesting experiment, but I feel like to be robust, this would have to consider some extractors rejecting the request as fatal, while others trigger the .or fallback. That is, I would in most cases only want fallback for Path mismatches, not Query and certainly not extractors like Extension that are often not at all related to user input.

Also I'm having somewhat of a hard time reviewing the code. Docs are looking good though.

@takkuumi
Copy link
Contributor

takkuumi commented Aug 1, 2022

if there is a fallback, when to trigger fallback? all of them rejected?

@davidpdrsn
Copy link
Member Author

if there is a fallback, when to trigger fallback? all of them rejected?

If an extractor rejects the fallback is called.

Cannot call the handler if the extractor doesn't succeed because we don't have a value of the right type. So we must call the next handler in the or chain.

@jplatte
Copy link
Member

jplatte commented Aug 1, 2022

Hm, maybe we should also have Either<A, B> .. Either8<A, B, C, D, E, F, G, H> extractors in axum-extra as a more fine-grained fallback thing? Those should be easier to use than separate Option extractors where you handle all of them failing manually. (although not as convenient as this PR if you really want entirely separate handler logic)

@davidpdrsn davidpdrsn enabled auto-merge (squash) August 10, 2022 10:02
@davidpdrsn davidpdrsn merged commit e79820d into main Aug 10, 2022
@davidpdrsn davidpdrsn deleted the handler-or branch August 10, 2022 10:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants