Eme
Eme

Reputation: 11

Problem with RestTemplate when including URL addresses in REST API request

I'm trying to obtain data from Botify's REST API to use it inside a project, which is also a REST API. I'm using an instance of Spring's RestTemplate class to make the actual requests to Botify, specifically the .exchange method as I need to pass Botify's key as a header parameter.

My problem comes when I need to call to a method of the endpoint which takes a URL as a part of the request's URI (not a parameter). Documentation of this endpoint is in https://developers.botify.com/api/reference/#!/Analysis/getUrlDetail

Basically the structure of the requests is like this:

/analyses/{username}/{project_slug}/{analysis_slug}/urls/{url}

The last part of that URI is a URL address, which needs to be encoded in UTF-8 to make it possible to separate it from the actual request.

The problem is (I believe) that the .exchange method always encodes the request, so what I try to send like this:

/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com

...ends up like this:

/analyses/myusername/myprojectname/myprojectslug/urls/https%253A%252F%252Fwww.example.com'

Which obviously doesn't work. This is an excerpt from the method that makes the call to Botify:

public String callBotifyEndpoint(String reportType, String parameters) throws UnsupportedEncodingException {
    String request = this.baseUri + "/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com"

    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "Token " + this.apiKey);
    HttpEntity<String> entity = new HttpEntity<>(headers);

    UriComponentsBuilder botifyQueryBuilder = UriComponentsBuilder.fromUriString(request);      
    String queryStringBuild = botifyQueryBuilder.build(true).toUriString();

    String botifyResult = null;

    try {
        System.out.println("Calling Botify API: " + queryStringBuild);
        ResponseEntity<String> response = botifyTemplate.exchange(queryStringBuild, HttpMethod.GET, entity, String.class);
        if(response.hasBody()) {
            botifyResult = response.getBody();
        }
    } catch(RestClientException ex) {
        ex.printStackTrace();
    }
    try {

    } catch (Exception e) {
        // TODO: handle exception
    }

    return botifyResult;    
}

In this line:

    botifyQueryBuilder.build(true).toUriString();

The "true" parameter indicates whether the data is already encoded or not. I've tried to disable it but the result is the same.

I've removed actual request generation process (along with my user and project's name) to simplify things, but this should return a response from Botify with the existing data for that URL.

Instead, it returns a 400 bad request error (which makes sense, because the URL is not correct).

I'm feeling like this may be a bug in RestTemplate's .exchange method, but maybe I'm not using it properly. Any suggestions?

Upvotes: 1

Views: 2133

Answers (1)

Krzysztof Tomaszewski
Krzysztof Tomaszewski

Reputation: 1144

Don't encode prematurly as you do here:

String request = this.baseUri + "/analyses/myusername/myprojectname/myprojectslug/urls/https%3A%2F%2Fwww.example.com";

Use parameter placeholders feature in RestTemplate instead of text concatenation.

Refer to: Spring RestTemplate GET with parameters

Upvotes: 1

Related Questions