MockServer с IPv6

Я запускаю клиент, который запрос к отправляетMockServer . При вызове MockServer с его адресом IPv4 все работает нормально, но при вызове через 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?

1 ответ

Есть RFC, в которых объясняется, что IPv6-адрес заключен в квадратные скобки ( [ и ]) при использовании порта или в URI. Например, RFC 4038, «Аспекты приложений перехода на IPv6» :

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; поэтому
нотацию префикса / длины нельзя использовать, если из контекста не ясно, что
она используется для указания префикса и длины, а не, например,
URI.

В некоторых особых случаях может потребоваться указать идентификатор зоны как часть адреса; например, fe80::1%eth0. Как правило, приложениям не требуется анализировать эти идентификаторы.

Парсеры IP-адресов должны поддерживать заключение IPv6-адреса в скобки, даже если адрес не используется вместе с
номером порта.
Не рекомендуется требовать, чтобы пользователь всегда указывал буквальный IP- адрес в скобках.

Обратите внимание, что некоторые приложения могут также по-разному представлять литералы адресов IPv6; например, SMTP [RFC2821] использует [IPv6: 2001:db8:: 1].

Обратите внимание, что использование адресных литералов для
прямого ввода в приложения общего назначения категорически не рекомендуется . Вместо этого следует использовать имена хостов и DNS.

Это изменит строку, в которой вы используете адрес:

        "Host" : [ "[2a01:c22:cc09:b600:81fb:91fe:4788:d52d]:8889" ],
Другие вопросы по тегам