I encountered an interesting problem while working on some integration tests.
I have a rest endpoint which has some query parameters which are time stamps specified in ISO-8601 (ex: 2020-07-08T23:54:36.931159+03:00). The dates are formatted using java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME
I create the request address by using:
//Query params are supplied in a Map<String,String>
String baseURL="http://localhost:" + this.port + uri
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
if (params != null) {
for (final Entry<String, String> entry : params.entrySet()) {
builder.queryParam(entry.getKey(), entry.getValue());
}
}
This will generate the following address:
http://localhost:8090/remainingAddress?fromDate=2020-07-08T23:54:36.834869+03:00&toDate=2020-07-08T23:54:36.931159+03:00
The problem is that the "+" sign was not encoded and stayed as it was originally present in the Map. On the receiving end the parameters are decoded thus resulting in the following date "020-07-08T23:54:36.834869 03:00" (notice the space instead of the +) and because of this when I attempt to parse the date using the same formatter it fails.
I tried encoding the parameters with java.net.URLEncoder.encode(String, Charset) before I add the value to the builder:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseURL);
if (params != null) {
for (final Entry<String, String> entry : params.entrySet()) {
var encoded=URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8);
builder.queryParam(entry.getKey(), encoded);
}
}
However this introduces "%" as a special character which actually triggers encoding in the builder thus the date parameter is encoded 2 times.
input string: 2020-07-09T00:14:15.230699+03:00
result after first encoding: 2020-07-09T00%3A14%3A15.230699%2B03%3A00
final result: http://localhost:8090/remainingAddress?fromDate=2020-07-09T00%253A14%253A15.230699%252B03%253A00&toDate=2020-07-09T00%253A14%253A15.31158%252B03%253A00
Upon execution of the request,I receive the following input when trying to parse the date: 2020-07-09T00%253A14%253A15.230699%252B03%253A00 (quite a mess).
Note this project uses Spring Boot V2.5.5.
My question is how should I offer the query parameters so they will be encoded correctly? Or perhaps this builder is not meant to be used with special characters?