2015-12-16 2 views
2

Я создал следующий простой тест для запроса Itunes:URL Spring RestTemplate getForObject не работает на Apple, 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") 
} 

И выход был неожиданным:

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

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

Оклейка сгенерированного URL в браузер делает дает ожидаемые результаты - художник вернулся.

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

Кроме того, жесткое кодирование запроса работает:

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

. , проблема возникает только для term запросов, содержащих пробелы.

Что пошло не так? Как собрать URL вручную, как исправить?

ответ

1

Кажется, что случай двойного кодирования пробелов. Из RestTemplate Javadoc:

Для каждого метода HTTP есть три варианта: два принимают шаблон строку URI и переменные URI (массив или карту), а третий принимает в URI. Обратите внимание, что для шаблонов URI предполагается, что кодировка равна , например. restTemplate.getForObject ("http://example.com/hotel лист") становится "http://example.com/hotel%20list". Это также означает, что если шаблон URI или переменные URI уже закодированы, произойдет двойное кодирование , например. http://example.com/hotel%20list будет http://example.com/hotel%2520list). Чтобы избежать этого, используйте вариант URI вариант для предоставления (или повторного использования) ранее кодированного URI. Чтобы подготовить такой URI с полным контролем над кодированием, рассмотрите возможность использования UriComponentsBuilder.

Таким образом, похоже, что getForObject на самом деле запросит https://itunes.apple.com/search?term=howling%2520wolf&entity=allArtist&limit=1 и, таким образом, приведет к пустым результатам. Вы всегда можете просто заменить пробелы на «+» в своем термине или попытаться сделать один из этих классов пропустить процесс кодирования.

+0

Первое, что я сделал, это попытаться использовать «+» вместо этого, но на самом деле это не сработало. –

+0

Удачи в противном случае? – Lukehey

+0

Нет, поскольку это был очень простой случай, который я использовал: 'val term = name.replace (oldChar = '', newChar = '+'); val response = URL ("$ {this.url}? entity = allArtist & limit = 1 & term = $ term"). readText() ', а затем сопоставлен с Jackson. Меня все еще немного беспокоит, что RestTemplate не работает. –

Смежные вопросы