Skip to content

Hard-coded proxy connect timeout in REST client overrides connect timeout of REST client. #48976

@Adelrisk

Description

@Adelrisk

Describe the bug

Due to a bad actor in an external network, my team and I have discovered that vert.x does not enable configuration of the the connect timeout for proxy clients. See issue eclipse-vertx/vert.x#5634

The Quarkus documentation outlines a connect timeout of 15 seconds, but in practice, the HTTP proxy client enforces a limit of 10 seconds, which cannot be configured or changed.

Expected behavior

If a HTTP proxy (or proxied server) requires 11 seconds to connect, and the Quarkus REST Client has a connect timeout of 15 seconds, I would expect the connection to be established.

Actual behavior

The HTTP Proxy client prematurely terminates the connection after 10 seconds.

jakarta.ws.rs.ProcessingException: io.netty.handler.proxy.ProxyConnectException: http, basic, /[<IPv6 address>]:7071 => <the bad actor>, timeout
	at org.jboss.resteasy.reactive.client.handlers.ClientSendRequestHandler$2.accept(ClientSendRequestHandler.java:225)
	at org.jboss.resteasy.reactive.client.handlers.ClientSendRequestHandler$2.accept(ClientSendRequestHandler.java:217)
	at io.smallrye.context.impl.wrappers.SlowContextualConsumer.accept(SlowContextualConsumer.java:21)
	at io.smallrye.mutiny.helpers.UniCallbackSubscriber.onFailure(UniCallbackSubscriber.java:62)
	at io.smallrye.mutiny.operators.uni.UniOperatorProcessor.onFailure(UniOperatorProcessor.java:55)
	at org.jboss.resteasy.reactive.client.AsyncResultUni.lambda$subscribe$1(AsyncResultUni.java:37)
	at io.vertx.core.impl.future.FutureImpl$4.onFailure(FutureImpl.java:188)
	at io.vertx.core.impl.future.FutureBase.lambda$emitFailure$1(FutureBase.java:75)
	at io.vertx.core.impl.ContextImpl.execute(ContextImpl.java:312)
	at io.vertx.core.impl.DuplicatedContext.execute(DuplicatedContext.java:168)
	at io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:72)
	at io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:278)
	at io.vertx.core.http.impl.HttpClientImpl.lambda$doRequest$4(HttpClientImpl.java:398)
	at io.vertx.core.net.impl.pool.Endpoint.lambda$getConnection$0(Endpoint.java:52)
	at io.vertx.core.http.impl.SharedClientHttpStreamEndpoint$Request.handle(SharedClientHttpStreamEndpoint.java:162)
	at io.vertx.core.http.impl.SharedClientHttpStreamEndpoint$Request.handle(SharedClientHttpStreamEndpoint.java:123)
	at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:342)
	at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:335)
	at io.vertx.core.net.impl.pool.SimpleConnectionPool$ConnectFailed$1.run(SimpleConnectionPool.java:380)
	at io.vertx.core.net.impl.pool.Task.runNextTasks(Task.java:43)
	at io.vertx.core.net.impl.pool.CombinerExecutor.submit(CombinerExecutor.java:91)
	at io.vertx.core.net.impl.pool.SimpleConnectionPool.execute(SimpleConnectionPool.java:244)
	at io.vertx.core.net.impl.pool.SimpleConnectionPool.lambda$connect$2(SimpleConnectionPool.java:258)
	at io.vertx.core.http.impl.SharedClientHttpStreamEndpoint.lambda$connect$2(SharedClientHttpStreamEndpoint.java:104)
	at io.vertx.core.impl.future.FutureImpl$4.onFailure(FutureImpl.java:188)
	at io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:81)
	at io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:278)
	at io.vertx.core.impl.future.Composition$1.onFailure(Composition.java:66)
	at io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:81)
	at io.vertx.core.impl.future.FailedFuture.addListener(FailedFuture.java:98)
	at io.vertx.core.impl.future.Composition.onFailure(Composition.java:55)
	at io.vertx.core.impl.future.FutureBase.emitFailure(FutureBase.java:81)
	at io.vertx.core.impl.future.FutureImpl.tryFail(FutureImpl.java:278)
	at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:342)
	at io.vertx.core.impl.ContextImpl.emit(ContextImpl.java:335)
	at io.vertx.core.net.impl.NetClientImpl.failed(NetClientImpl.java:351)
	at io.vertx.core.net.impl.NetClientImpl.lambda$connectInternal2$6(NetClientImpl.java:323)
	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:603)
	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:570)
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:505)
	at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:649)
	at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:642)
	at io.netty.util.concurrent.DefaultPromise.setFailure(DefaultPromise.java:123)
	at io.vertx.core.net.impl.ChannelProvider$3$1.exceptionCaught(ChannelProvider.java:235)
	at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:346)
	at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:325)
	at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:317)
	at io.netty.handler.proxy.ProxyHandler.failPendingWritesAndClose(ProxyHandler.java:356)
	at io.netty.handler.proxy.ProxyHandler.setConnectFailure(ProxyHandler.java:349)
	at io.netty.handler.proxy.ProxyHandler.access$100(ProxyHandler.java:41)
	at io.netty.handler.proxy.ProxyHandler$2.run(ProxyHandler.java:201)
	at io.netty.util.concurrent.PromiseTask.runTask(PromiseTask.java:98)
	at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:156)
	at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:173)
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:166)
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
	at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:998)
	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:1583)
Caused by: io.netty.handler.proxy.ProxyConnectException: http, basic, /[<IPv6 address>]:7071 => <the bad actor>, timeout
	... 11 more

How to Reproduce?

Use a HTTP proxy server and establish a connection, where one of the involved parties takes over 10 seconds to establish the connection.

(Or see eclipse-vertx/vert.x#5634 (comment) )

Output of uname -a or ver

No response

Output of java -version

No response

Quarkus version or git rev

No response

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

Vertx have already begun work on a fix, enabling a new connectTimeout configuration for the proxy client. See PR eclipse-vertx/vert.x#5650

The developers have stated interest in backporting the fix. eclipse-vertx/vert.x#5634 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions