Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mounting a Vert.x sub-router on a path with path parameters

I want to create a URL structure for my Vert.x Web powered API that makes it clear how some entities are "contained" inside other entities and how you "traverse the entity path" to find child entities, so I'm thinking of using something like this to address a "grand child" (I don't expect anything deeper than a grand child):

GET /entity/:parent_id/sub-entity/:child_id/subsub-entity/:grandchild_id

So normally my Router configuration will look something like this:

router.get("/entity/:parent_id/sub-entity/:child_id/subsub-entity/:grandchild_id")
    .handler(r -> {
       HttpServerRequest req = r.request();
       Minipart p = Entities.get(req.getParameter("parent_id"))
           .getPart(req.getParameter("child_id"))
           .getMinipart(req.getParameter("grandchild_id"));
       // do something with p
    });

When I add a lot of operations (each entity class at each level has catalog and create operations, and each level entity instance has get, update and delete operations, as well as a few other tidbits), my router class gets really large.

I was thinking of using sub-routers to offload the sub-entity management down the line, so the Entities Router configuration might do:

router.mountSubRouter("/entity/:parent_id/sub-entity", PartsRouter.init(vertx));

and then PartsRouter can do:

router.get("/:child_id").handler(r -> {
    String parentEntityId = r.request().getParameter("parent_id");
    Entity parent = Entities.get(parentEntityId);
    String myid = r.request().getParameter("child_id");
    Part myself = parent.getPart(myid);
    // do something with myself
});

But when I do try that and try to access the sub-router operations, I get a 404 error from Vert.x...

Update:

Apparently Vert.x explicitly does not support this - it threw an exception that my wrapper code just logged and ignored, saying:

java.lang.IllegalArgumentException: Can't use patterns in subrouter mounts

So, is there another way to achieve what I'm trying to do (split a large router configuration into a proper class hierarchy)?

like image 602
Guss Avatar asked Nov 08 '22 08:11

Guss


1 Answers

I can image 2 ways of solving your problem:

The first one would be to have a initial handler that processes the common part of the request and calls next so the following one will continue where the first stopped e.g.:

router.route("/entity/:parent_id/sub-entity", ctx -> {
  // common part here...
  ctx.next();
});

And then:

router.route("/entity/:parent_id/sub-entity/:child_id", ctx -> {
  String parentEntityId = r.request().getParameter("parent_id");
  Entity parent = Entities.get(parentEntityId);
  String myid = r.request().getParameter("child_id");
  Part myself = parent.getPart(myid);
  // do something with myself
});

Alternatively you can use internal redirects, so you handle the initial code as before but instead of calling next() you redirect to another URL. In that case you should store in the context what you want to reuse since the request will be restarted in the new location.

like image 110
Paulo Lopes Avatar answered Nov 14 '22 23:11

Paulo Lopes