Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullPointerException is thrown if WebClient is used with Apache Httpclient and cookies are disabled. #34132

Open
pmv opened this issue Dec 20, 2024 · 0 comments
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@pmv
Copy link

pmv commented Dec 20, 2024

Running this unit test:

(note the disableCookieManagement() option)

import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;

public class WebClientTest {

    @Test
    void cookiesDisabledTest() {
        CloseableHttpAsyncClient noCookieHttpClient = HttpAsyncClientBuilder.create()
                .disableCookieManagement().build();
        WebClient webClient = WebClient.builder()
                .clientConnector(new HttpComponentsClientHttpConnector(noCookieHttpClient))
                .build();
        webClient.get().uri("https://spring.io/").exchange().block();
    }
}

throws this exception:

org.springframework.web.reactive.function.client.WebClientRequestException: Cannot invoke "org.apache.hc.client5.http.cookie.CookieSpec.parse(org.apache.hc.core5.http.Header, org.apache.hc.client5.http.cookie.CookieOrigin)" because "cookieSpec" is null

	at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:137)
	Suppressed: The stacktrace has been enhanced by Reactor, refer to additional information below: 
Error has been observed at the following site(s):
	*__checkpoint ⇢ Request to GET https://spring.io/ [DefaultWebClient]
Original Stack Trace:
		at org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:137)
		at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:55)
		at reactor.core.publisher.Mono.subscribe(Mono.java:4576)
		at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103)
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222)
		at reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222)
		at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onError(MonoIgnoreThen.java:280)
		at reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:205)
		at org.springframework.http.client.reactive.HttpComponentsClientHttpConnector$ResultCallback.failed(HttpComponentsClientHttpConnector.java:186)
		at org.apache.hc.core5.concurrent.BasicFuture.failed(BasicFuture.java:166)
		at org.apache.hc.core5.concurrent.ComplexFuture.failed(ComplexFuture.java:79)
		at org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$2$1.failed(InternalAbstractHttpAsyncClient.java:315)
		at org.apache.hc.core5.concurrent.BasicFuture.failed(BasicFuture.java:166)
		at org.apache.hc.core5.reactive.ReactiveResponseConsumer.failed(ReactiveResponseConsumer.java:143)
		at org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$2.failed(InternalAbstractHttpAsyncClient.java:353)
		at org.apache.hc.client5.http.impl.async.AsyncRedirectExec$1.failed(AsyncRedirectExec.java:246)
		at org.apache.hc.client5.http.impl.async.AsyncHttpRequestRetryExec$1.failed(AsyncHttpRequestRetryExec.java:195)
		at org.apache.hc.client5.http.impl.async.AsyncProtocolExec$1.failed(AsyncProtocolExec.java:295)
		at org.apache.hc.client5.http.impl.async.HttpAsyncMainClientExec$1.failed(HttpAsyncMainClientExec.java:136)
		at org.apache.hc.client5.http.impl.async.LoggingAsyncClientExchangeHandler.failed(LoggingAsyncClientExchangeHandler.java:177)
		at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamHandler.failed(ClientHttp1StreamHandler.java:291)
		at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer.terminate(ClientHttp1StreamDuplexer.java:181)
		at org.apache.hc.core5.http.impl.nio.AbstractHttp1StreamDuplexer.shutdownSession(AbstractHttp1StreamDuplexer.java:165)
		at org.apache.hc.core5.http.impl.nio.AbstractHttp1StreamDuplexer.onException(AbstractHttp1StreamDuplexer.java:407)
		at org.apache.hc.core5.http.impl.nio.AbstractHttp1IOEventHandler.exception(AbstractHttp1IOEventHandler.java:90)
		at org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler.exception(ClientHttp1IOEventHandler.java:41)
		at org.apache.hc.client5.http.impl.async.LoggingIOSession$1.exception(LoggingIOSession.java:253)
		at org.apache.hc.core5.reactor.ssl.SSLIOSession$1.exception(SSLIOSession.java:243)
		at org.apache.hc.core5.reactor.InternalDataChannel.onException(InternalDataChannel.java:181)
		at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:55)
		at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:176)
		at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:125)
		at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92)
		at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
		at java.base/java.lang.Thread.run(Thread.java:1583)
	Suppressed: java.lang.Exception: #block terminated with an error
		at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:104)
		at reactor.core.publisher.Mono.block(Mono.java:1779)
		at WebClientTest.cookiesDisabledTest(WebClientTest.java:16)
		at java.base/java.lang.reflect.Method.invoke(Method.java:580)
		at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
		at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.NullPointerException: Cannot invoke "org.apache.hc.client5.http.cookie.CookieSpec.parse(org.apache.hc.core5.http.Header, org.apache.hc.client5.http.cookie.CookieOrigin)" because "cookieSpec" is null
	at org.springframework.http.client.reactive.HttpComponentsClientHttpResponse.adaptCookies(HttpComponentsClientHttpResponse.java:79)
	at org.springframework.http.client.reactive.HttpComponentsClientHttpResponse.<init>(HttpComponentsClientHttpResponse.java:62)
	at org.springframework.http.client.reactive.HttpComponentsClientHttpConnector$ResponseCallback.completed(HttpComponentsClientHttpConnector.java:153)
	at org.springframework.http.client.reactive.HttpComponentsClientHttpConnector$ResponseCallback.completed(HttpComponentsClientHttpConnector.java:135)
	at org.apache.hc.core5.concurrent.BasicFuture.completed(BasicFuture.java:148)
	at org.apache.hc.core5.reactive.ReactiveResponseConsumer.consumeResponse(ReactiveResponseConsumer.java:127)
	at org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$2.handleResponse(InternalAbstractHttpAsyncClient.java:305)
	at org.apache.hc.client5.http.impl.async.AsyncRedirectExec$1.handleResponse(AsyncRedirectExec.java:208)
	at org.apache.hc.client5.http.impl.async.AsyncHttpRequestRetryExec$1.handleResponse(AsyncHttpRequestRetryExec.java:134)
	at org.apache.hc.client5.http.impl.async.AsyncProtocolExec$1.handleResponse(AsyncProtocolExec.java:230)
	at org.apache.hc.client5.http.impl.async.HttpAsyncMainClientExec$1.consumeResponse(HttpAsyncMainClientExec.java:243)
	at org.apache.hc.client5.http.impl.async.LoggingAsyncClientExchangeHandler.consumeResponse(LoggingAsyncClientExchangeHandler.java:142)
	at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamHandler.consumeHeader(ClientHttp1StreamHandler.java:249)
	at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer.consumeHeader(ClientHttp1StreamDuplexer.java:348)
	at org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer.consumeHeader(ClientHttp1StreamDuplexer.java:80)
	at org.apache.hc.core5.http.impl.nio.AbstractHttp1StreamDuplexer.onInput(AbstractHttp1StreamDuplexer.java:299)
	at org.apache.hc.core5.http.impl.nio.AbstractHttp1IOEventHandler.inputReady(AbstractHttp1IOEventHandler.java:64)
	at org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler.inputReady(ClientHttp1IOEventHandler.java:41)
	at org.apache.hc.client5.http.impl.async.LoggingIOSession$1.inputReady(LoggingIOSession.java:238)
	at org.apache.hc.core5.reactor.ssl.SSLIOSession.decryptData(SSLIOSession.java:617)
	at org.apache.hc.core5.reactor.ssl.SSLIOSession.access$200(SSLIOSession.java:74)
	at org.apache.hc.core5.reactor.ssl.SSLIOSession$1.inputReady(SSLIOSession.java:202)
	at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:143)
	at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:51)
	at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:176)
	at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:125)
	at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92)
	at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
	at java.base/java.lang.Thread.run(Thread.java:1583)

When cookies are disabled, it seems there is no CookieSpec in the context here:
https://github.com/spring-projects/spring-framework/blob/v6.2.1/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java#L72

so the exception happens here:
https://github.com/spring-projects/spring-framework/blob/v6.2.1/spring-web/src/main/java/org/springframework/http/client/reactive/HttpComponentsClientHttpResponse.java#L79

I assume this is a legitimate use case? In the case of a null CookieSpec, an empty map could be returned.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 20, 2024
@bclozel bclozel added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Dec 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

3 participants