问题描述
我正在运行一个客户端,向 MockServer 发出一些请求。使用 IPv4 地址调用 MockServer 时一切正常,但通过 IPv6 MockServer 调用时抛出异常:
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)
看起来 MockServer 在解析主机和端口时有一些问题。甚至可以将 MockServer 与 IPv6 一起使用吗?
解决方法
有些 RFC 解释了当您使用端口或 URI 时将 IPv6 地址括在方括号([
和 ]
)中。例如,RFC 4038,Application Aspects of IPv6 Transition:
5.1。 IP 地址的表示格式
许多应用程序使用 IP 地址来识别网络节点并
建立到目标地址的连接。例如,使用
客户端/服务器模型,客户端通常需要一个IP地址作为
连接到服务器的应用程序参数。这个IP地址是
通常以演示格式提供,作为字符串。有
移植IP地址表示格式的两个问题:
分配的内存和演示格式的管理。
通常,分配给包含 IPv4 地址的内存
作为字符串的表示不能包含 IPv6 地址。
应修改应用程序以防止缓冲区溢出
可能通过更大的 IPv6 地址。
IPv4 和 IPv6 不使用相同的表示格式。 IPv4 使用
点 (.) 分隔以十进制表示法编写的四个八位字节,以及
IPv6 使用冒号 (:) 分隔以
编写的每对八位字节
十六进制表示法 [RFC3513]。在必须能够
的情况下
例如,指定带有地址的端口号(见下文),它
可能需要将地址放在正方形内
方括号 [TextRep]。
IP 地址解析器的一个特殊问题出现在输入
实际上是IP地址和端口号的组合。使用 IPv4
这些通常与冒号相结合;例如,“192.0.2.1:80”。
然而,这种方法对于 IPv6 来说是不明确的,因为冒号是
已经用于构造地址。
因此,取端口号的IP地址解析器 用冒号分隔应该以某种方式区分 IPv6 地址。 一种方法是将地址括在括号中,就像使用 统一资源定位符(URL)[RFC2732];例如, http://[2001:db8::1]:80.
有些应用还需要指定IPv6前缀和长度:
前缀长度应插入方括号外,
如果使用;例如,[2001:db8::]/64 或 2001:db8::/64 而不是
[2001:db8::/64]。请注意,前缀/长度符号在语法上是
与合法的 URI 无法区分;因此,前缀/长度
当上下文不清楚
时,不得使用符号
它用于指定前缀和长度,而不是例如 a
URI。
在某些特定情况下,可能需要给一个区域 标识符作为地址的一部分;例如,fe80::1%eth0。在 一般来说,应用程序不需要解析这些标识符。
IP 地址解析器应支持将 IPv6 地址包含在
括号,即使地址没有与 a
一起使用
端口号。要求用户始终提供文字 IP
不推荐用括号括起来的地址。
请注意,某些应用程序也可能表示 IPv6 地址 文字不同;例如,SMTP [RFC2821] 使用 [IPv6:2001:db8::1]。
请注意,对于
,强烈建议不要使用地址文字
应用程序的通用直接输入。主机名和 DNS
应该改用。
那会改变你使用地址的行:
"Host" : [ "[2a01:c22:cc09:b600:81fb:91fe:4788:d52d]:8889" ],