I found a bug in the HTTP server when the client is sending an H2C HTTP/2 request, and the HTTP server is using vertx-web
The scenario is when a request is sent without any relative URI:
for example http://localhost:6000
In that case the call to HTTP client is with:
RequestOptions requestOptions = new RequestOptions();
requestOptions.setHost(127.0.0.1);
requestOptions.setPort(8080);
requestOptions.setURI("");
In the HTTP Server I'm getting this exception:
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(String.java:658)
at io.vertx.core.http.impl.HttpUtils.parsePath(HttpUtils.java:226)
at io.vertx.core.http.impl.Http2ServerRequestImpl.path(Http2ServerRequestImpl.java:296)
at io.vertx.ext.web.impl.HttpServerRequestWrapper.<init>(HttpServerRequestWrapper.java:27)
at io.vertx.ext.web.impl.RoutingContextImplBase.<init>(RoutingContextImplBase.java:45)
at io.vertx.ext.web.impl.RoutingContextImpl.<init>(RoutingContextImpl.java:63)
at io.vertx.ext.web.impl.RouterImpl.accept(RouterImpl.java:79)
at io.vertx.core.http.impl.Http2ServerConnection.lambda$onHeadersRead$0(Http2ServerConnection.java:130)
at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:342)
at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:200)
at io.vertx.core.http.impl.Http2ServerConnection.onHeadersRead(Http2ServerConnection.java:127)
at io.vertx.core.http.impl.Http2ConnectionBase.onHeadersRead(Http2ConnectionBase.java:191)
at io.vertx.core.http.impl.Http2ServerConnection.onHeadersRead(Http2ServerConnection.java:48)
at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder$FrameReadListener.onHeadersRead(DefaultHttp2ConnectionDecoder.java:321)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader$1.processFragment(DefaultHttp2FrameReader.java:457)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readHeadersFrame(DefaultHttp2FrameReader.java:464)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.processPayloadState(DefaultHttp2FrameReader.java:254)
at io.netty.handler.codec.http2.DefaultHttp2FrameReader.readFrame(DefaultHttp2FrameReader.java:160)
at io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder.decodeFrame(DefaultHttp2ConnectionDecoder.java:118)
at io.netty.handler.codec.http2.Http2ConnectionHandler$FrameDecoder.decode(Http2ConnectionHandler.java:373)
at io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:433)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
at java.lang.Thread.run(Thread.java:745)
and the request is never served by the HTTP server.
If I change the HTTP client request to:
RequestOptions requestOptions = new RequestOptions();
requestOptions.setHost("127.0.0.1");
requestOptions.setPort(8080);
requestOptions.setURI("\");
Then the HTTP server receives the request and serves it just fine.
I also verified that the issue is only in the HTTP Server in vert.x-web.
The HTTP server in vert.x core is not having this issue.
I believe the problem is in io.vertx.ext.web.impl.HttpServerRequestWrapper's constructor:
I found a bug in the HTTP server when the client is sending an H2C HTTP/2 request, and the HTTP server is using vertx-web
The scenario is when a request is sent without any relative URI: for example http://localhost:6000 In that case the call to HTTP client is with:
In the HTTP Server I'm getting this exception:
and the request is never served by the HTTP server.
If I change the HTTP client request to:
Then the HTTP server receives the request and serves it just fine.
I also verified that the issue is only in the HTTP Server in vert.x-web. The HTTP server in vert.x core is not having this issue.
I believe the problem is in io.vertx.ext.web.impl.HttpServerRequestWrapper's constructor:
This calls
The path is not null, but it's empty "" and then HttpUtils.parsePath(String uri) makes an assumptions that uri is not empty, and fails here: