SpringのRestTemplateでは、プラス記号(+)がエンコードされない。

そのため、クエリパラメータにプラス記号が含まれているような外部APIに対してのリクエストで受け取る際に問題が生じてしまう。

解決

リクエストURIに対してプラス記号をエンコード文字列に置換してやればよい。

今回は次のようなインターセプターで実装してみた。

PlusSymbolEncodeInterceptor.java@Component
public class PlusSymbolEncodeInterceptor implements ClientHttpRequestInterceptor {
    
    @Override
    public ClientHttpResponse intercept(
            HttpRequest request,
            byte[] body,
            ClientHttpRequestExecution execution) throws IOException {
        
        HttpRequest encodeRequest = new HttpRequestWrapper(request) {
            @Override
            public URI getURI() {
                return encodeUri(super.getRequest());
            }
        }
        
        return execution.execute(encodeRequest, body);
    }
    
    URI getUri(HttpRequest request) {
        URI uri = request.getURI();        
        return UriComponents.fromUri(uri)
                .replaceQuery(StringUtils.replace(uri.getRawQuery(), "+", "%2B")) // 「+」を「%2B」に置換
                .build(true)
                .toUri();
    }
}

あとは、RestTemplateBuilderなどを使ってインターセプターとして設定してやれば良い。

RestTemplate restTemplate = restTemplateBuilder
    .additionalInterceptors(new PlusSymbolEncodeInterceptor());
    .build();

エンコードがされない特殊文字は他にもあるが同様の方法でエンコードしてやれば良い。