Tim,
Sorry, but a couple of sentences won't cut it here. My last post was an
attempt at brevity and it clearly did not work. :)
The current Vert.x HTTP server behaviour appears to be readily
misunderstood, as evidenced by your own comments in this mailing list
indicating that the problem of people not realising they need to
register body handlers immediately for an HTTPServerRequest has been
raised in this mailing list frequently (e.g.
https://groups.google.com/d/msg/vertx/dH8QP-GQgrY/ZTJKazXSE9MJ).
This misunderstanding appears to be encouraged by the way the vertx-apex
router classes encourage people to use the Vert.x HTTP server interface
because it gives the impression that you can set up handlers for
different routes without having to initially prepare global body
handlers. While these impressions are wrong, it appears to be a common
failing that it not remedied by Vert.x documentation or the behaviour of
the Vert.x HTTP server API.
I would like the Vert.x team to consider a possible solution to this
problem of ready misunderstanding.
Bruno Salmon, who submitted the bugzilla issue
https://bugs.eclipse.org/bugs/show_bug.cgi?id=433459, has proposed a
change to the HTTP server API that would help alert people that they are
using the interface incorrectly by throwing an exception if a body
handler is registered too late. However, this has not been implemented.
Tamas Foldesi, who commented on the same bugzilla issue, also proposed a
change to the API to have it cache the body of the request and provide
it when a body handler is registered. I expect this is not practical
because for a server in a high traffic environment, the amount of
information that could end up being cached could impose excessive memory
requirements on the application.
So I am proposing another alternative solution that, as far as I can
determine, would allow the HTTP server API to behave the way people
(currently mistakenly) expect it to and without breaking any current use
of that API or introducing significant performance cost.
My proposal is to have the Vert.x HTTP server pause receiving a request
after headers have been received and automatically resume it when an end
handler is registered or an HttpServerResponse end() method is called.
Existing applications that currently register body handlers immediately
will effectively never have their connection paused. New applications
that carry out header processing, for example for authentication, before
registering body handlers would find their code would work instead of
failing without any indication of cause. People using vertx-apex could
have route handlers that register different body handlers for different
routes after common authentication processing without this failing
without any indication of cause.
- Mark.
P.S. To get behaviour in the current Vert.x 3 implementation that
approaches what my proposal would hopefully provide, we are doing the
following (using vertx-apex):
router = Router.router(vertx);
/*
* This must be the first route registered.
*/
router.route().handler((RoutingContext ctx) -> {
ctx.addBodyEndHandler((Void v) -> {
ctx.request().resume();
});
ctx.request().pause();
ctx.next();
});
Then we need to make sure to resume receiving the request whenever a
body or end handler is registered, e.g.:
ctx.request().resume().endHandler(...);
As long as we write all the code that registers body or end handlers,
this pattern is not overly difficult to maintain, however, if the
broader community start providing "re-usable" route handlers that we
might like to be able to take advantage of, expecting this pattern to be
followed universally would not be reasonable. So removing the
requirement for this pattern by having the Vert.x HTTP server API behave
in such a way that it is not necessary would be preferable.