Search code examples
springspring-bootspring-webfluxspring-webclient

How can I save cookies between Spring WebClient requests?


I would like to use Spring Boot WebClient in my project to access a REST-API. The first request performs the login into the REST-API and receives a cookie as response. This cookie is used as an "API-Token" for all another requests.

However, the WebClient does not seem to store the cookie. Do I have to do this myself? If so, what is the best way to proceed?

Following is my sample source code. The second request does not use the cookies from the first.

// ### 1. API-Call to get the cookie ###
ClientResponse clientResponse = webClient
        .get()
        .uri("/api/")
        .headers(headers -> headers.setBasicAuth(user,passwd)
        .exchange()
        .block();

// ### Debug Cookie ###
if (clientResponse.statusCode().is2xxSuccessful()) {
    for (String key : clientResponse.cookies().keySet()) {
        LOG.debug("key:" + key + " value: " + clientResponse.cookies().get(key).get(0).getValue() );
    }
}   

// ### 2.API-Call (with cookie) ###
webClient
    .get()
    .uri("/api/document/4711")
    .retrieve()
    .onStatus(HttpStatus::is2xxSuccessful, r -> {
        for (String key : r.cookies().keySet()) {
            LOG.debug("key:" + r.cookies().get(key).get(0).getValue());
        }
        return Mono.empty();
    })
    .onStatus(HttpStatus::is4xxClientError, r -> {
        System.out.println("2 4xx error");
        for (String key : r.cookies().keySet()) {
            LOG.debug("key:" + r.cookies().get(key).get(0).getValue());
        }
        return Mono.error(new RuntimeException("" + r.statusCode().value()));
    })
    .onStatus(HttpStatus::is5xxServerError, response -> {
        LOG.error("2 5xx error");
        return Mono.error(new RuntimeException("5xx"));
    })
    .bodyToMono(String.class)
    .block();

Solution

  • To store the cookies, we changed to the Jetty HttpClient (org.eclipse.jetty.client.HttpClient).

    See this answer for how to enable it: How to use the Spring WebClient with Jetty, instead of Netty?.