vertx-web icon indicating copy to clipboard operation
vertx-web copied to clipboard

No waiting possible in handlers called after response.end()

Open efagerho opened this issue 3 years ago • 0 comments

Describe the feature

Vert.x Web routers don't seem to contain an interface which allows creating handlers that add a timer to requests that has to fire before anything is written out to the wire. The closest to this is ctx.addHeadersEndHandler(), but the handler is called synchronously, so it's not possible to have the handler wait e.g. a few milliseconds before writing output. The use case that I have is that I would like to write a simple router that prevents timing attacks against e.g. login and similar APIs. In other words, I would like to do something equivalent to Thread.sleep() in the handler. Of course, what I would actually like to do is use vertx.setTimer(). In other words,

public void handle(RoutingContext ctx) {
  long start = System.nanoTime();

  ctx.addHeadersEndHandler(v -> {
      public void handle(RoutingContext ctx) {
        long end = System.nanoTime();
        vertx.SetTimer(..., ...)
      });
  ctx.next();
  }

However, this won't work, since the response goes out the wire right after the headers end handler finishes execution, i.e. there's nothing I can do to wait for the timer to expire short of blocking the thread.

Use cases

Latency masking from APIs in security sensitive APIs. This can be implemented as a base class for sensitive handlers, but it would not be as trivial to integrate into existing code bases as being able to write a handler that I could just add to the router.

I would like to be able to write code like

router
    .route()
    .handler(new LatencyNormalizer())
    .handler(new MyHandler())

which would make it easy to add timing attack protections to existing code bases. However, there seems to be no API currently that would make it possible to implement the LatencyNormalizer() handler.

Contribution

If this is somewhat simple to implement in a way that would be possible to merge, then I'm happy to take a shot at it myself if someone can provide me with a plan for implementing this.

One possible option that I see is adding something like addEndInterceptor() method to RoutingContext, which would cause response() to return a wrapper around HttpServerResponse. The wrapper would intercept calls to HttpServerResponse.end() and forward those to the interceptor handler, which could then postpone calling end on the wrapped HttpServerResponse object.

Maybe there's some contrived way to implement what I want with the current APIs and maybe there's a simpler way to extend the current interfaces, so that writing such a handler is possible.

efagerho avatar Feb 12 '22 11:02 efagerho