Search code examples
vert.xvertx-httpclient

Optional path parameter in vertx


I want to use a get request to get optional path parameters in a single end point . For example :-

if user hit below api :-

  1. /metric/monitor/:id or /metric/:id

here id is path parameter than i need to route to the same function in a single end point using get request. How can i do the same ?


Solution

  • You can specify a route using regular expressions. Assuming the id is a number:

    router.getWithRegex( "\\/metric(\\/monitor)?\\/(?<ID>\\d+)" ).respond( this::monitor );
    

    and then read the value:

    long id = Long.parseLong( ctx.pathParam( "ID" ) );
    

    This is how I usually declare the route using Vert.x Web 4.3.1:

    public class MyVerticle extends AbstractVerticle {
    
        @Override
        public void start(Promise<Void> startPromise) {
            Router router = Router.router( vertx );
            BodyHandler bodyHandler = BodyHandler.create();
            router.post().handler( bodyHandler );
    
            router.getWithRegex( "\\/metric(\\/monitor)?\\/(?<ID>\\d+)" ).respond( this::monitor );
    
            // Keeping track of it so that I can close it later
            this.httpServer = vertx.createHttpServer();
            final Future<HttpServer> startHttpServer = httpServer
                    .requestHandler( router )
                    .listen( HTTP_PORT )
                    .onSuccess( v -> LOG.infof( "✅ HTTP server listening on port %s", HTTP_PORT ) );
    
            startHttpServer
                    .onSuccess( s -> startPromise.complete() )
                    .onFailure( startPromise::fail );
        }
    
        private Future<Result> monitor(RoutingContext ctx) {
            long id = Long.parseLong( ctx.pathParam( "ID" ) );
            Result result = ... // Do something
            return Future.succeededFuture(result);
        }
    
    

    More details about routing with regular expressions are available in the documentation.

    But, to be fair, creating two separate entry points seems easier for this case:

    router.get( "/metric/monitor/:id" ).respond( this::monitor );
    router.get( "/metric/:id" ).respond( this::monitor );