reactor / reactor-netty

TCP/HTTP/UDP/QUIC client/server with Reactor over Netty
https://projectreactor.io
Apache License 2.0
2.55k stars 633 forks source link

failure when writing tls control frames #2838

Closed eljoemed closed 1 year ago

eljoemed commented 1 year ago

Hi @GregoireW @violetagg
I'm experiencing exactly the same issue as @GregoireW at diference that I'm mocking proxy with wiremock as a forward proxy. when I desable the proxy properties the call to the https service is working. Once I configure the proxy I get the same error than @GregoireW . bellow my webclient config if someone can help. Thanks

Call to the service

client.post()
         .uri(PATH_FLD_CREATE)
         .bodyValue(body)
         .retrieve()
         .bodyToMono(FdaResponse.class)

Webclient

WebClient.builder()
                 .baseUrl(properties.url())
                 .defaultHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE)
                 .clientConnector(getConnector())
                 .filter(this::encryptPayload)
                 .filter(this::signAuthorizationHeader)
                 .build();

Netty HttpClient

private ReactorClientHttpConnector getConnector() {
   return new ReactorClientHttpConnector(
      HttpClient.create()
         .proxyWithSystemProperties()
         .option(CONNECT_TIMEOUT_MILLIS, properties.timeout())
         .responseTimeout(ofMillis(properties.timeout()))
         .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(properties.timeout(), MILLISECONDS))
                              .addHandlerLast(new WriteTimeoutHandler(properties.timeout(), MILLISECONDS)))
   );
}

Proxy configuration

private void configureProxy() {
   if (StringUtils.isNotEmpty(properties.proxy())) {
      URI proxyURI = URI.create(properties.proxy());
      System.setProperty("http.proxyHost", proxyURI.getHost());
      System.setProperty("http.proxyPort", valueOf(proxyURI.getPort()));
   }
}

application-test.yml

project:
  wiremock:
    enabled: true
    port: 9080
client:
  mastercard:
    url: https://sandbox.api.mastercard.com
    proxy: http://127.0.0.1:9090

forward_proxy.json

{
  "priority": 5,
  "request": {
    "urlPattern": ".*",
    "method": "ANY"
  },
  "response": {
    "status": 200,
    "proxyBaseUrl": "https://external.service.com"
  }
}

Error logs

2023-06-20 19:37:44,308  WARN [r.netty.http.client.HttpClientConnect   ,ctor-http-nio-1] (,,,,,) : [45ac42a9, L:/127.0.0.1:49834 - R:/127.0.0.1:9090] The connection observed an error

javax.net.ssl.SSLException: failure when writing TLS control frames
    at io.netty.handler.ssl.SslHandler.setHandshakeFailureTransportFailure(SslHandler.java:1907)
    at io.netty.handler.ssl.SslHandler.access$600(SslHandler.java:170)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:935)
    at io.netty.handler.ssl.SslHandler$2.operationComplete(SslHandler.java:930)
    at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:590)
    at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:557)
    at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:492)
    at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:636)
    at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:629)
    at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:118)
    at io.netty.channel.PendingWriteQueue.safeFail(PendingWriteQueue.java:288)
    at io.netty.channel.PendingWriteQueue.removeAndFailAll(PendingWriteQueue.java:186)
    at io.netty.handler.proxy.ProxyHandler.failPendingWrites(ProxyHandler.java:434)
    at io.netty.handler.proxy.ProxyHandler.failPendingWritesAndClose(ProxyHandler.java:351)
    at io.netty.handler.proxy.ProxyHandler.setConnectFailure(ProxyHandler.java:346)
    at io.netty.handler.proxy.ProxyHandler.channelRead(ProxyHandler.java:266)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
    at io.netty.handler.proxy.HttpProxyHandler$HttpClientCodecWrapper.channelRead(HttpProxyHandler.java:272)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: io.netty.handler.proxy.HttpProxyHandler$HttpProxyConnectException: http, none, /127.0.0.1:9090 => sandbox.api.mastercard.com/<unresolved>:443, status: 500 Server Error
    at io.netty.handler.proxy.HttpProxyHandler.handleResponse(HttpProxyHandler.java:200)
    at io.netty.handler.proxy.ProxyHandler.channelRead(ProxyHandler.java:257)
    ... 24 common frames omitted
violetagg commented 1 year ago

@eljoemed Please provide an example that we can run or described in details how to reproduce the issue with the snippets provided above.

eljoemed commented 1 year ago

``Thank you @violetagg I'm trying to make an HTTPS call to mastercard API from my µService. everything is working fine with the WebClient (code provided in initial post). Now I have to configure a proxy. but in our dev environment we don't have a proxy for test (and we can not have it, it's an internal problem). So what we did is mocking proxy with wiremock for unit test. when I execute the test without filling the proxy param (application.properties) it works. but when I fill the proxy param I get the mentionned error. NB : I don't need ssl conf in my netty httpclient to call Mastercard API (I just need to signe the authorization header and encrypt the payload) Wish it's clear for you and thank you for your time and help

violetagg commented 1 year ago

Is it possible that you are seeing these

https://github.com/reactor/reactor-netty/issues/617 https://github.com/wiremock/wiremock/issues/379

eljoemed commented 1 year ago

I was on it. Thank you @violetagg. I saw you answer about hoverfly. I tested it localy and it works like a charm. Now I'm trying to add it in the bundle to install it in kubernetes dev namespace to try. I'll keep you informed Thank you

violetagg commented 1 year ago

@eljoemed Let me close this one as there is no issue in Reactor Netty.