I am trying to configure my HttpServer to respond to bad content lengths with a response code of 400. When testing my server using the given curl command : curl -i -X POST -H "Content-Length: bad-length"
http://localhost:9992/monitoring/status I get an empty reply from the server: "curl: (52) Empty reply from server". The below exception appears in the logs. I understand that the netty HttpUtil will always throw the NumberFormatException for a bad content-length, but is there a way I can define an exception handler to return my own response?
ERROR io.vertx.core.net.impl.ConnectionBase - Unhandled exception
java.lang.NumberFormatException: For input string: "bad-length"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[?:1.8.0_171]
at java.lang.Long.parseLong(Long.java:589) ~[?:1.8.0_171]
at java.lang.Long.parseLong(Long.java:631) ~[?:1.8.0_171]
at io.netty.handler.codec.http.HttpUtil.getContentLength(HttpUtil.java:178) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.http.HttpObjectDecoder.contentLength(HttpObjectDecoder.java:635) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.http.HttpObjectDecoder.readHeaders(HttpObjectDecoder.java:625) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.http.HttpObjectDecoder.decode(HttpObjectDecoder.java:227) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428) ~[gateway-vertx.jar:?]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[gateway-vertx.jar:?]
at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:60) ~[gateway-vertx.jar:?]
at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) ~[gateway-vertx.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1414) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) ~[gateway-vertx.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) ~[gateway-vertx.jar:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:945) ~[gateway-vertx.jar:?]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:146) ~[gateway-vertx.jar:?]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645) ~[gateway-vertx.jar:?]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580) ~[gateway-vertx.jar:?]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497) ~[gateway-vertx.jar:?]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459) ~[gateway-vertx.jar:?]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:886) ~[gateway-vertx.jar:?]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [gateway-vertx.jar:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
Below is an example code snippet from my verticle that creates the HttpServer.
@Override
public void start(Future<Void> startFuture) throws Exception {
// Configure router
Router router = Router.router(vertx);
router.exceptionHandler(this::defaultExceptionHandler);
vertx.exceptionHandler(this::defaultExceptionHandler);
MonitoringApi monitoringApi = new MonitoringApi(vertx);
router.mountSubRouter("/monitoring", monitoringApi.getRouter());
// Start server
int port = config().getInteger("monitoring.port");
vertx.createHttpServer()
.exceptionHandler(this::defaultExceptionHandler)
.requestHandler(router::accept)
.listen(port, res -> {
if (res.succeeded()) {
logger.debug("Started on port {}", port);
startFuture.complete();
} else {
startFuture.fail(res.cause());
}
});
}
private void defaultExceptionHandler(Throwable throwable) {
logger.error("Caught throwable", throwable);
}
Thank you!