I started using the new RestClient today, and stumbled upon a surprise in the API/behavior.

Creating a client instance can be done with e.g. RestClient.create("https://my.baseurl.com"), which makes sense; you need only once to provide the base URL of, say, an API you are a consuming.

Then, when doing requests, there are two .uri(..) overloads accepting a String and a URI. The String parameter name for .uri(String, Object...) is uri, so both these methods are named "uri", and accepts the concept of a URI as argument, though represented by different types. My expectation is that these methods behave in the same way.

The documentation for .uri(String, Object...) says explicitly "If a UriBuilderFactory was configured for the client (e.g. wth a base URI it will be used to expand the URI template". And this will indeed resolve the given uri wrt to the baseUrl of the RestClient.

The documentation for .uri(URI) though says "Specify the URI using an absolute, fully constructed URI", and invoking this with e.g. URI.create("/my/path") will disregard the baseUrl of the RestClient, and issuing the request results in an exception about missing scheme in the url.

I wondered if the requirement of supplying a fully constructed URI to .uri(URI) could be lifted, and maybe resolve it against any defined baseUrl if the given URI is not absolute?

See the below test for some context:

URI baseUrl = URI.create("https://spring.io");
URI pathOnly = URI.create("/projects");
URI fullUrl = URI.create("https://spring.io/projects");

assertFalse(pathOnly.isAbsolute());
assertTrue(fullUrl.isAbsolute());
assertEquals(fullUrl, baseUrl.resolve(pathOnly));

Given the code above, I would like this to be possible:

RestClient client = RestClient.create(baseUrl.toASCIIString()); // would also be nice with a method accepting a URI as the baseUrl.
URI resolvedRequestUrl = client.get().uri(pathOnly).exchange((request, response) -> request.getURI()); // currently throws
assertEquals(fullUrl, resolvedRequestUrl);

One motivation is that I prefer to give absolute paths to other resources in the same API in responses, not actually fully constructed URLs, and I also prefer to map these links in the responses to URIs in my objects, to gain some type safety, as an absolute path (to my understanding) is a (relative) URI (see e.g. https://stackoverflow.com/a/18505331). Mapping a response to an object, I then cannot pass links (being URIs) directly to the UriSpec.uri(URI), but must convert them to String first.

Any thought on this? Perhaps there may be caveats I have not considered?

Comment From: quaff

I agree that URI should be expanded also, if it's accepted for RestClient, then same thing should apply to RestTemplate, see https://github.com/spring-projects/spring-framework/pull/27188.