javalin / javalin

A simple and modern Java and Kotlin web framework

Home Page:https://javalin.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Before handlers are executed even though another path already matched?

juv opened this issue · comments

commented

Actual behavior (the bug)
When configuring routes like this:

        path(
            "/outer-path",
            () -> {
              path(
                  "/inner-path/a-bit-more-specific",
                  () -> {
                    before(ctx -> LOGGER.info("before of /inner-path/a-bit-more-specific"));
                    get("/hi", ctx -> ctx.result("hi"));
                  });

              path(
                  "/inner-path",
                  () -> {
                    before(ctx -> LOGGER.info("before of /inner-path"));
                    get(ctx -> ctx.result("this is not executed"));
                    get("/{some-input-id}", ctx -> ctx.result("this is not executed either 2"));
                  });
            });

and creating a GET request to /outer-path/inner-path/a-bit-more-specific/hi will execute both before handlers and return the string hi.

Mixing both /{path-params} paths and /static paths inside of the same endpoint group sometimes creates unwanted effects. Therefore I tried to split the handlers up into two endpoint groups but the before handlers are still executed even when the request itself would not always match a "real http" handler in the endpoint group.

Expected behavior
Only the before handler of endpoint group /inner-path/a-bit-more-specific is executed, similar to how the request is only triggering the get("/hi", ctx -> ctx.result("hi")); handler after all.

To Reproduce
use curl http://localhost:{your javalin port}/outer-path/inner-path/a-bit-more-specific/hi

Additional context
Console log:

2024-05-13 15:45:13,308 [main] INFO  io.javalin.Javalin - You are running Javalin 6.1.3 (released March 2, 2024).
2024-05-13 15:45:13,403 [JettyServerThreadPool-43] INFO  d.v.e.c.i.s.b.webservice.Webserver - before of /inner-path/a-bit-more-specific
2024-05-13 15:45:13,403 [JettyServerThreadPool-43] INFO  d.v.e.c.i.s.b.webservice.Webserver - before of /inner-path
...
2024-05-13 15:45:13,420 [main] INFO  io.javalin.Javalin - Stopping Javalin ...

What you have is:

path("/outer-path", () -> {
    path("/inner-path", () -> {
        before(ctx -> LOGGER.info("before of /inner-path")); // before everything under "/inner-path/*"
        get(ctx -> ctx.result("this is not executed"));
        get("/{some-input-id}", ctx -> ctx.result("this is not executed either 2"));

        path("/a-bit-more-specific", () -> { // before everything under "/inner-path/a-bit-more-specific/*"
            before(ctx -> LOGGER.info("before of /inner-path/a-bit-more-specific"));
            get("/hi", ctx -> ctx.result("hi"));
        });
    });
});

If you look at it like this, do you still only expect 1 before handler to fire?

commented

What you have is:

path("/outer-path", () -> {
    path("/inner-path", () -> {
        before(ctx -> LOGGER.info("before of /inner-path")); // before everything under "/inner-path/*"
        get(ctx -> ctx.result("this is not executed"));
        get("/{some-input-id}", ctx -> ctx.result("this is not executed either 2"));

        path("/a-bit-more-specific", () -> { // before everything under "/inner-path/a-bit-more-specific/*"
            before(ctx -> LOGGER.info("before of /inner-path/a-bit-more-specific"));
            get("/hi", ctx -> ctx.result("hi"));
        });
    });
});

If you look at it like this, do you still only expect 1 before handler to fire?

Hi, absolutely not. Thanks for clarifying that these separated endpoint groups will be merged and are not treated as individual ones after all and this is expected.