Spring の UriComponentsBuilder のちょっと罠っぽいところ
UriComponentsBuilder は以下のように、URIの構築を簡単にできるやつです。 Spring とか使っている人だと使ったことあると思います。
String result = UriComponentsBuilder .fromUriString("https://example.com/") .queryParam("hoge", "あ") .toUriString(); assertThat(result).isEqualTo("https://example.com/?hoge=%E3%81%82");
最近使っていて気づいたのですが、UriComponentsBuilder.fromUriString(str)
or UriComponentsBuilder.fromHttpUrl(str)
に渡す URI string に query がついている場合、その部分も encode されるという挙動をします。
つまり、予め encodeしていると2重に encode されてしまうわけです。
こんな感じです。
String result = UriComponentsBuilder .fromHttpUrl("https://example.com/?nextPath=%2Fpath%2Fto%2Fsome%2Fpage") // "/path/to/some/page" .queryParam("hoge", "あ") .toUriString(); assertThat(result).isNotEqualTo( "https://example.com/?nextPath=%2Fpath%2Fto%2Fsome%2Fpage&hoge=%E3%81%82"); assertThat(result).isEqualTo( "https://example.com/?nextPath=%252Fpath%252Fto%252Fsome%252Fpage&hoge=%E3%81%82");
んー。個人的には、queryParam で指定した部分だけのほうが直感的だと思いますが...。
参考までに、Apache HttpClient にある URIBuilder だと query 部分が2重にencodeされるということはありません。
String result = new URIBuilder("https://example.com/?nextPath=%2Fpath%2Fto%2Fsome%2Fpage") .addParameter("hoge", "あ") .build().toString(); assertThat(result).isEqualTo( "https://example.com/?nextPath=%2Fpath%2Fto%2Fsome%2Fpage&hoge=%E3%81%82");