2

I created the following simple test to query iTunes:

@Test
fun loadArtist()
{
    val restTemplate = RestTemplate()

    val builder = UriComponentsBuilder.fromHttpUrl("https://itunes.apple.com/search")
    builder.queryParam("term", "howling wolf")
    builder.queryParam("entity", "allArtist")
    builder.queryParam("limit", 1)

    println("\n\nURL ${builder.toUriString()}")

    val result = restTemplate.getForObject(builder.toUriString(), String::class.java);
    println("Got artist: $result")
}

And the output was unexpected:

URL https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1
Got artist: 

{
 "resultCount":0,
 "results": []
}

Pasting the generated URL into a browser does give expected results - artist returned.

https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1

Also, hard-coding the query works:

val result = restTemplate.getForObject("https://itunes.apple.com/search?term=howling%20wolf&entity=allArtist&limit=1", String::class.java);

. . the problem only seems to occur for term queries that include spaces.

What went wrong? Other than assemble the URL by hand, how to fix?

nhaarman
  • 98,571
  • 55
  • 246
  • 278
Jasper Blues
  • 28,258
  • 22
  • 102
  • 185

1 Answers1

1

Seems like a case of double encoding the whitespace. From the RestTemplate Javadoc:

For each HTTP method there are three variants: two accept a URI template string and URI variables (array or map) while a third accepts a URI. Note that for URI templates it is assumed encoding is necessary, e.g. restTemplate.getForObject("http://example.com/hotel list") becomes "http://example.com/hotel%20list". This also means if the URI template or URI variables are already encoded, double encoding will occur, e.g. http://example.com/hotel%20list becomes http://example.com/hotel%2520list). To avoid that use a URI method variant to provide (or re-use) a previously encoded URI. To prepare such an URI with full control over encoding, consider using UriComponentsBuilder.

So it looks like getForObject will actually query for https://itunes.apple.com/search?term=howling%2520wolf&entity=allArtist&limit=1 and thus result in an empty result. You can always just replace whitespaces with a "+" in your term or try to make one of those classes skip the encoding process.

Lukehey
  • 1,284
  • 1
  • 11
  • 20
  • The first thing I did was try using "+" instead, but it didn't seem to work, actually. – Jasper Blues Dec 16 '15 at 15:32
  • No, since it was a very simple case I just used: `val term = name.replace(oldChar = ' ', newChar = '+'); val response = URL("${this.url}?entity=allArtist&limit=1&term=$term").readText()` and then mapped with Jackson. It still bothers me a little that RestTemplate didn't work though. – Jasper Blues Dec 16 '15 at 16:09