Handling special characters in uri

152 Views Asked by At

The below mentioned is my requestUrl "http://localhost:80/v1/accounts/60a362bd6b84a37effc8f5a3/name/QA Analyst" I am using the following code

UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(requestUrl);
ResponseEntity<RoleResponse> responseEntity = null;
HttpEntity<?> entity = new HttpEntity(RestUtil.getHeaders(this.appSecret));

try {
  responseEntity = this.restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, RoleResponse.class, new Object[0]);
} catch (Exception var9) {
  log.error("Error occurred while getting role by name for accountId {}", accountId, var9);
  throw new RestClientException("rest_client_exception", "Unable to get role by name for account");
}

In the service which is running on port 80 with java 8 version, I can see the following uri being hit "v1/accounts/60a362bd6b84a37effc8f5a3/name/QA%2520Analyst" but this uri is being handled and can get responsecode 200. Now I migrated to java 17 and the request is throwing 400 BAD_REQUEST. What is the reason and how can I handle this ? The restTemplate I am using is of org.springframework.web.client

2

There are 2 best solutions below

0
On

It's a bad practice to have a space in your request URI. Check this answer on why a URL should not contain a literal space. I think the issue in your case is that the space character is being encoded twice. A space character gets URL encoded to %20 and a % character is encoded to %25. Thus your URL gets encoded twice to %2520. I suspect that builder.toUriString() maybe encoding it once followed by another encoding in restTemplate.exchange(). I'm not sure but it is quite likely that one of the implementations changed in Java 17 and that is why it is a terrible idea and design to have a space in your URI. I would rather have it as a query parameter that ensures the safe encoding of most characters.

http://localhost:80/v1/accounts/{accountId}?name=QA%20Analyst

A good practice for RESTful API design is that path parameters are used to identify a specific resource, while query parameters are used to sort/filter those resources. In your case, it appears that you are doing a filtering/search by name.

0
On

It seems that fromHttpUrl() method encodes url and then in RestTemplate#exchange your url is encoded twice. So, try this:

  String uri = UriComponentsBuilder.fromHttpUrl("http://localhost:80")
                  .path("/v1/accounts/{accountId}/name/{roleName}")
                  .buildAndExpand("60a362bd6b84a37effc8f5a3", "QA Analyst")
                  .toUriString();

   System.out.println(uri); // not encoded yet: http://localhost:80/v1/accounts/60a362bd6b84a37effc8f5a3/name/QA Analyst

  responseEntity = this.restTemplate.exchange(uri, HttpMethod.GET, entity, RoleResponse.class, new Object[0]);