2

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 を組み立てる以外に、どのように修正しますか?

4

1 に答える 1

1

空白を二重にエンコードする場合のようです。RestTemplate Javadoc から:

各 HTTP メソッドには 3 つのバリアントがあります。2 つは URI テンプレート文字列と URI 変数 (配列またはマップ) を受け入れ、3 つ目は URI を受け入れます。URI テンプレートの場合、エンコーディングが必要であると想定されていることに注意してください。たとえば、restTemplate.getForObject(" http://example.com/hotel list") は " http://example.com/hotel%20list " になります。これは、URI テンプレートまたは URI 変数がすでにエンコードされている場合、二重エンコードが発生することも意味します。たとえば、http://example.com/hotel%20listhttp://example.com/hotel%2520listになります)。これを回避するには、URI メソッドのバリアントを使用して、以前にエンコードされた URI を提供 (または再利用) します。エンコーディングを完全に制御できるこのような URI を準備するには、UriComponentsBuilder の使用を検討してください。

したがって、getForObject は実際にhttps://itunes.apple.com/search?term=howling%2520wolf&entity=allArtist&limit=1を照会し、空の結果になるようです。いつでも用語の空白を「+」に置き換えるか、これらのクラスのいずれかをエンコード プロセスをスキップさせることができます。

于 2015-12-16T13:36:26.547 に答える