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 URI
s) 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.