-
Notifications
You must be signed in to change notification settings - Fork 691
Description
Problem:
Make a request with a WebClient with a cookie that contains an illegal character (like @)
Client will hang indefinetely or timeout (if set)
I would except a proper exception to be thrown
Expected Behavior
Exception (java.lang.IllegalArgumentException: Cookie name contains an invalid char: @
at io.netty.handler.codec.http.cookie.CookieEncoder.validateCookie(CookieEncoder.java:38)) is thrown
Actual Behavior
WebClient hangs/timeouts. Only debug log is shown if debug is enabled:
`2025-09-02T14:33:02.274+03:00 DEBUG 70865 --- [r-http-kqueue-1] r.netty.channel.ChannelOperations : [a5cd68f7-1, L:/100.123.2.78:49463 - R:/10.0.20.124:443] An outbound error could not be processed
java.lang.IllegalArgumentException: Cookie name contains an invalid char: @
at io.netty.handler.codec.http.cookie.CookieEncoder.validateCookie(CookieEncoder.java:38)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.FluxConcatIterable] :
reactor.core.publisher.Flux.concat(Flux.java:426)
org.springframework.http.client.reactive.AbstractClientHttpRequest.doCommit(AbstractClientHttpRequest.java:170)
Error has been observed at the following site(s):
*_Flux.concat ⇢ at org.springframework.http.client.reactive.AbstractClientHttpRequest.doCommit(AbstractClientHttpRequest.java:170)
| Flux.then ⇢ at org.springframework.http.client.reactive.AbstractClientHttpRequest.doCommit(AbstractClientHttpRequest.java:170)
*___Mono.defer ⇢ at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:456)
Original Stack Trace:
at io.netty.handler.codec.http.cookie.CookieEncoder.validateCookie(CookieEncoder.java:38)
at io.netty.handler.codec.http.cookie.ClientCookieEncoder.encode(ClientCookieEncoder.java:217)
at io.netty.handler.codec.http.cookie.ClientCookieEncoder.encode(ClientCookieEncoder.java:165)
at reactor.netty.http.client.HttpClientOperations.beforeMarkSentHeaders(HttpClientOperations.java:629)
at reactor.netty.http.HttpOperations.markSentHeaderAndBody(HttpOperations.java:364)
at reactor.netty.http.client.HttpClientOperations.onOutboundComplete(HttpClientOperations.java:652)
at reactor.netty.channel.ChannelOperations.onComplete(ChannelOperations.java:258)
at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onComplete(MonoIgnoreElements.java:89)
at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:121)
at reactor.core.publisher.FluxConcatIterable.subscribe(FluxConcatIterable.java:60)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76)
at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:457)
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:716)
at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:207)
at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:468)
at reactor.netty.channel.ChannelOperationsHandler.channelActive(ChannelOperationsHandler.java:62)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:260)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:231)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelActive(CombinedChannelDuplexHandler.java:412)
at io.netty.channel.ChannelInboundHandlerAdapter.channelActive(ChannelInboundHandlerAdapter.java:69)
at io.netty.channel.CombinedChannelDuplexHandler.channelActive(CombinedChannelDuplexHandler.java:211)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:260)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:238)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:231)
at reactor.netty.tcp.SslProvider$SslReadHandler.userEventTriggered(SslProvider.java:723)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:398)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:376)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:368)
at io.netty.handler.logging.LoggingHandler.userEventTriggered(LoggingHandler.java:222)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:398)
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:376)
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:368)
at io.netty.handler.ssl.SslHandler.setHandshakeSuccess(SslHandler.java:1995)
at io.netty.handler.ssl.SslHandler.wrapNonAppData(SslHandler.java:1016)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1555)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1377)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1428)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:530)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
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:1357)
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:868)
at io.netty.channel.kqueue.AbstractKQueueStreamChannel$KQueueStreamUnsafe.readReady(AbstractKQueueStreamChannel.java:543)
at io.netty.channel.kqueue.AbstractKQueueChannel$AbstractKQueueUnsafe$1.run(AbstractKQueueChannel.java:380)
at io.netty.util.concurrent.AbstractEventExecutor.runTask$$$capture(AbstractEventExecutor.java:173)
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute$$$capture(AbstractEventExecutor.java:166)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.kqueue.KQueueEventLoop.run(KQueueEventLoop.java:300)
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)`
Steps to Reproduce
@Test
public void repoCase() {
WebClient.builder()
.get()
.uri("your-uri")
.cookie("cookie-with-@", "true")
.retrieve(String.class)
.block(ofSeconds(10))
}Possible Solution
Workaraound is to wrap cookies in URLEncoder.encode("cookie-with-@", US_ASCII)
Your Environment
- Reactor netty http version(s) used: 1.2.4
- spring-webflux: 6.2.5
- JVM version (
java -version): 21.0.5 - OS and version (eg.
uname -a): macos 15.6 (24G84)