Skip to content

Conversation

@jponge
Copy link
Member

@jponge jponge commented Jul 22, 2025

This is useful when building elaborated routes in a programmatic fashion (e.g., predicates).

This is useful when building elaborated routes in a programmatic
fashion (e.g., predicates).
@jponge jponge requested review from tsegismont and vietj July 23, 2025 05:38
Copy link
Contributor

@tsegismont tsegismont left a comment

Choose a reason for hiding this comment

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

Thanks for your proposal @jponge

So far, I fail to see how this helps building routers as trees rather than chains. Perhaps can you share a non-trivial example that help to understand the use case?

The trivial ones don't make the code shorter and more concise. For example:

router.get("/branching").handler(BranchingHandler.create(
        rc -> rc.request().headers().contains("Foo"),
        rc -> {
          String foo = rc.request().getHeader("Foo");
          rc.response().end("Foo: " + foo);
        },
        rc -> rc.response().end("N/A")
      ));

Is not shorter and more concise than:

router.get("/branching").handler(rc -> {
    if (rc.request().headers().contains("Foo")) {
        String foo = rc.request().getHeader("Foo");
        rc.response().end("Foo: " + foo);
    }
    else {
        rc.response().end("N/A");
    }
});

@jponge
Copy link
Member Author

jponge commented Jul 24, 2025

If you're building routes manually for your API, then yes, I'd do what you did in the second snippet and roll my own handler with a conditional branching structure 😃

Where this gets more complicated is when you are building routes programmatically, and especially when you want branching and not just chains. A good example is when you mount a handler in the chain that doesn't provide any way back / vertx-http-proxy is a good example (and you can't just leverage failure recovery at the router level).

The use-case I have in mind is building predicates, so you can enable a route handler only if certain conditions are met (e.g., some request header is present, etc). Having such a building block is helpful, especially when you add routes programmatically.

@tsegismont
Copy link
Contributor

A good example is when you mount a handler in the chain that doesn't provide any way back

Wouldn't this do the trick?

Handler<RoutingContext> handler = createMyAwesomeHandler();
router.get("/branching").handler(rc -> {
    if (myConditionIsMet()) {
        handler.handle(rc);
    }
    else {
        rc.next();
    }
});

@jponge
Copy link
Member Author

jponge commented Jul 24, 2025

It does, but having a building block like this is also a viable route

@tsegismont
Copy link
Contributor

It does, but having a building block like this is also a viable route

Not sure what you mean with "like this". Did you mean like the proposed BranchingHandler? In this case, the following code:

Handler<RoutingContext> handler = createMyAwesomeHandler();
router.get("/branching").handler(BranchingHandler.create(
    rc -> myConditionIsMet(),
    handler::handle
));

is not much more concise or readable than:

Handler<RoutingContext> handler = createMyAwesomeHandler();
router.get("/branching").handler(rc -> {
    if (myConditionIsMet()) {
        handler.handle(rc);
    } else {
        rc.next();
    }
});

Sorry if I'm missing something obvious.

@jponge
Copy link
Member Author

jponge commented Jul 24, 2025

I'm not looking for conciseness but composability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants