使用 IPv6 的 MockServer

问题描述

我正在运行一个客户端,向 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" ],

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...