MockServer with IPv6

309 views Asked by At

I'm running a client issuing some request against MockServer. When calling MockServer with its IPv4 address everything works well but when calling it via IPv6 MockServer throws an exception:

    021-07-23 13:57:39 5.11.1 SEVERE 8889 exception processing request:

  {
    "method" : "GET",
    "path" : "/mypath",
    "headers" : {
      "Host" : [ "[2a01:c22:cc09:b600:50e7:2959:9dda:7aa8]:8889" ],
      "User-Agent" : [ "Go-http-client/1.1" ],
      "Accept-Encoding" : [ "gzip" ],
      "content-length" : [ "0" ]
    },
    "keepAlive" : true,
    "secure" : true
  }

 error:

  For input string: "c22"
 
java.lang.NumberFormatException: For input string: "c22"
       at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
       at java.base/java.lang.Integer.parseInt(Integer.java:652)
       at java.base/java.lang.Integer.parseInt(Integer.java:770)
       at org.mockserver.model.HttpRequest.socketAddressFromHostHeader(HttpRequest.java:1036)
       at org.mockserver.client.NettyHttpClient.sendRequest(NettyHttpClient.java:70)
       at org.mockserver.mock.action.http.HttpActionHandler.processAction(HttpActionHandler.java:216)
       at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:151)
       at org.mockserver.netty.HttpRequestHandler.channelRead0(HttpRequestHandler.java:48)
       at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
       at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
       at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at org.mockserver.dashboard.DashboardWebSocketHandler.channelRead(DashboardWebSocketHandler.java:141)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at org.mockserver.closurecallback.websocketregistry.CallbackWebSocketServerHandler.channelRead(CallbackWebSocketServerHandler.java:55)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
       at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
       at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
       at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at org.mockserver.netty.unification.PortUnificationHandler.switchToHttp(PortUnificationHandler.java:260)
       at org.mockserver.netty.unification.PortUnificationHandler.decode(PortUnificationHandler.java:138)
       at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
       at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
       at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1518)
       at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1267)
       at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1314)
       at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
       at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440)
       at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
       at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
       at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
       at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
       at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
       at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
       at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
       at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
       at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
       at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at java.base/java.lang.Thread.run(Thread.java:834)

It looks like MockServer has some issues parsing host and port. Is it even possible to use MockServer with IPv6?

1

There are 1 answers

1
Ron Maupin On

There are RFCs that explain you surround the IPv6 address in square brackets ([ and ]) when you use a port, or in a URI. For example, RFC 4038, Application Aspects of IPv6 Transition:

5.1. Presentation Format for an IP Address

Many applications use IP addresses to identify network nodes and to establish connections to destination addresses. For instance, using
the client/server model, clients usually need an IP address as an
application parameter to connect to a server. This IP address is
usually provided in the presentation format, as a string. There are
two problems when porting the presentation format for an IP address:
the allocated memory and the management of the presentation format.

Usually, the memory allocated to contain an IPv4 address
representation as a string is unable to contain an IPv6 address.
Applications should be modified to prevent buffer overflows made
possible by the larger IPv6 address.

IPv4 and IPv6 do not use the same presentation format. IPv4 uses a dot (.) to separate the four octets written in decimal notation, and
IPv6 uses a colon (:) to separate each pair of octets written in
hexadecimal notation [RFC3513]. In cases where one must be able to
specify, for example, port numbers with the address (see below), it
may be desirable to require placing the address inside the square
brackets [TextRep].

A particular problem with IP address parsers comes when the input is actually a combination of IP address and port number. With IPv4 these are often coupled with a colon; for example, "192.0.2.1:80".
However, this approach would be ambiguous with IPv6, as colons are
already used to structure the address.

Therefore, the IP address parsers that take the port number separated with a colon should distinguish IPv6 addresses somehow. One way is to enclose the address in brackets, as is done with Uniform Resource Locators (URLs) [RFC2732]; for example, http://[2001:db8::1]:80.

Some applications also need to specify IPv6 prefixes and lengths:
The prefix length should be inserted outside of the square brackets,
if used; for example, [2001:db8::]/64 or 2001:db8::/64 and not
[2001:db8::/64]. Note that prefix/length notation is syntactically
indistinguishable from a legal URI; therefore, the prefix/length
notation must not be used when it isn't clear from the context that
it's used to specify the prefix and length and not, for example, a
URI.

In some specific cases, it may be necessary to give a zone identifier as part of the address; for example, fe80::1%eth0. In general, applications should not need to parse these identifiers.

The IP address parsers should support enclosing the IPv6 address in brackets, even when the address is not used in conjunction with a
port number. Requiring that the user always give a literal IP
address enclosed in brackets is not recommended.

Note that some applications may also represent IPv6 address literals differently; for example, SMTP [RFC2821] uses [IPv6:2001:db8::1].

Note that the use of address literals is strongly discouraged for
general-purpose direct input to the applications. Host names and DNS should be used instead.

That would change the line where you use the address:

  "Host" : [ "[2a01:c22:cc09:b600:81fb:91fe:4788:d52d]:8889" ],