1

I'm trying to use Traverson in my Spring Boot application to consume an external HAL-api. While doing so I get the exception org.apache.http.ProtocolException: Target host is not specified on the first hop, i.e. Traverson calls my baseUri without problems and with set target host, but seems to "forget" the host on the first hop.

And this is the code calling it:

    override fun doStuff() {

        // baseUri gets injected by class and is of form "https://my.host.com"
        val startUri = UriComponentsBuilder.fromUriString(baseUri)
                // If dms is declared as first hop, Traverson would call baseUri before first hop which returns a html website and results in an error -> dms has to be part of Traverson baseUri
                .pathSegment("dms")
                .build()
                .toUri();

        val authHeader = HttpHeaders()
        // bearerToken gets injected by class and is not relevant for the problem
        authHeader.set(HttpHeaders.AUTHORIZATION, bearerToken)

        val restTemplate = RestTemplateBuilder()
                .rootUri(baseUri)
                .defaultHeader(HttpHeaders.AUTHORIZATION, bearerToken)
                .build()
        // httpRequestFactory gets injected by class and is used to configure SSL, should not matter for the problem
        restTemplate.requestFactory = httpRequestFactory

        val repoId: String = Traverson(startUri, MediaTypes.HAL_JSON)
                .setRestOperations(restTemplate)
                .follow("$._links.allrepos.href")
                .withHeaders(authHeader)
                .toObject("$.repositories[0].id")

        log.debug("Repo id is $repoId")
    }

This is the return of the Traverson baseUri (https://my.host.com/dms):

{
    _links: {
        allrepos: {
            href: "/dms/r"
        }
    }
}

When executing this code, Traverson get's the link I'm searching for ("/dms/r") but when trying to follow it, it executes a call to "/dms/r" instead of "https://my.host.com/dms/r".

Am I missing something?

Every bit of help is very much appreciated!

EDIT 1: It is possible to achieve my goal with following code. But if I have to resort to this option, I would instead use restTemplate directly without url discovery, since Traverson is just too inconvenient to use in this case.

        val allReposLink = Traverson(startUri, MediaTypes.HAL_JSON)
                .setRestOperations(restTemplate)
                .follow("$._links.allrepos.href")
                .withHeaders(headers)
                .asLink()
                .href

        val allReposUri = UriComponentsBuilder.fromUriString(baseUri)
                .pathSegment(allReposLink)
                .build()
                .toUri()
        val repoId = Traverson(allReposUri, MediaTypes.HAL_JSON)
                .setRestOperations(restTemplate)
                .follow("$.repositories[0].id")
                .withHeaders(headers)
                .asLink()
                .href

It should be possible to do it like this:

// DOES NOT WORK
        val repoId: String = Traverson(startUri, MediaTypes.HAL_JSON)
                .setRestOperations(restTemplate)
                .follow("allrepos")
                .withHeaders(headers)
                .toObject("$.repositories[0].id")
Antonio Dell
  • 497
  • 5
  • 17

0 Answers0