Open guidbona opened 5 years ago
It seems that the issue:
Also affects sendForm() and sendStream().
I found the reason: HttpContext
uses pipe mechanism to write the body:
if (body instanceof ReadStream<?>) {
ReadStream<Buffer> stream = (ReadStream<Buffer>) body;
if (request.headers == null || !request.headers.contains(HttpHeaders.CONTENT_LENGTH)) {
req.setChunked(true);
}
stream.pipeTo(req, ar -> {
if (ar.failed()) {
responseFuture.tryFail(ar.cause());
req.reset();
}
});
In the Pipe constructor, endHandler
of the stream
is set to complete the future:
src.endHandler(result::tryComplete);
src.exceptionHandler(result::tryFail);
Later, when we start the pipe operation in public void to()
, there's an exception handler set for the request destination:
ws.exceptionHandler(err -> result.tryFail(new WriteException(err)));
However, it is called too late, when the result future is already completed, because we finished reading the stream
! That's why all exceptions in the request are ignored.
As a workaround you can use sendJson()
, sendJsonObject()
or sendBuffer
, because they don't use this pipe mechanism to write the request body, and allow the exceptions to be propagated:
} else {
Buffer buffer;
if (body instanceof Buffer) {
buffer = (Buffer) body;
} else if (body instanceof JsonObject) {
buffer = Buffer.buffer(((JsonObject)body).encode());
} else {
buffer = Buffer.buffer(Json.encode(body));
}
req.exceptionHandler(responseFuture::tryFail);
req.end(buffer);
}
See block starting at
https://github.com/vert-x3/vertx-web/blob/6b6dd6d48e2ca65ff40f95754d067755c52a6548/vertx-web-client/src/main/java/io/vertx/ext/web/client/impl/HttpContext.java#L470
Happens setting a timeout on the request, but I guess all other exceptions are lost as well. This means the handler of the HttpRequest is never called.