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" ],