Skip to content

Inconsist baseurl behaviour between RestClient and WebClient #32185

@wimdeblauwe

Description

@wimdeblauwe

I migrated some code that uses the declarative http interface support of Spring from WebClient to RestClient as the underlying implementation. Our code started failing on the staging server after that. I managed to trace the problem to a difference in handling of the base url between RestClient and WebClient.

The difference is easily seen via this test program:

import org.springframework.web.client.RestClient;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class Test {

  public static void main(String[] args) throws InterruptedException {
    WebClient webClient = WebClient.builder()
        .baseUrl("numbersapi.com").build();

    Mono<String> bodilessEntity = webClient.get().uri("/42").retrieve().bodyToMono(String.class);
    String block = bodilessEntity.block();
    System.out.println("block = " + block);

    RestClient restClient = RestClient.builder()
        .baseUrl("numbersapi.com")
        .build();
    String viaRestClient = restClient.get().uri("/42").retrieve().body(String.class);
    System.out.println("viaRestClient = " + viaRestClient);
  }
}

Note how the base url does not specify a scheme (http or https) in both cases. However, with WebClient, this is not an issue and the call to the remote service is done. With RestClient, an exception is thrown:

Exception in thread "main" java.lang.IllegalArgumentException: URI with undefined scheme
	at java.net.http/jdk.internal.net.http.common.Utils.newIAE(Utils.java:326)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.checkURI(HttpRequestBuilderImpl.java:79)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.uri(HttpRequestBuilderImpl.java:71)
	at java.net.http/jdk.internal.net.http.HttpRequestBuilderImpl.uri(HttpRequestBuilderImpl.java:43)
	at org.springframework.http.client.JdkClientHttpRequest.buildRequest(JdkClientHttpRequest.java:136)
	at org.springframework.http.client.JdkClientHttpRequest.executeInternal(JdkClientHttpRequest.java:95)
	at org.springframework.http.client.AbstractStreamingClientHttpRequest.executeInternal(AbstractStreamingClientHttpRequest.java:70)
	at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.exchangeInternal(DefaultRestClient.java:468)
	at org.springframework.web.client.DefaultRestClient$DefaultRequestBodyUriSpec.retrieve(DefaultRestClient.java:439)

Maybe it should not have worked in the first place with WebClient, I don't know. But maybe it would be good to have the same behaviour?

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: declinedA suggestion or change that we don't feel we should currently apply

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions