Spring RestTemplate getForObject URL 不适用于 Apple iTunes

Spring RestTemplate getForObject URL not working for Apple iTunes

我创建了以下简单测试来查询 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 查询中。

出了什么问题?除了手动 assemble 和 URL 之外,如何修复?

似乎是对空格进行双重编码的情况。来自 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.

所以看起来 getForObject 实际上会查询 https://itunes.apple.com/search?term=howling%2520wolf&entity=allArtist&limit=1,因此结果为空。您始终可以在您的术语中用“+”替换空格,或者尝试使其中一个空格 类 跳过编码过程。