はじめに
何気ない Cookie ヘッダが API サーバをきずつけることもあります
詳細
RestTemplate
といえば Spring で WebAPI を叩くときによく使うだろうと思います。
シンプルな例だと、以下のようなコードで http 通信を行って得られたレスポンスを任意のクラスにマッピングすることができます。
restTemplate = restTemplateBuilder.requestFactory(requestFactorySupplier)
.build();
HogeResponse hogeResponse = restTemplate.getForObject("http://hoge.example.com/", HogeResponse.class);
この RestTemplate
インスタンスを作る過程で RequestFactory
の指定をしなかった場合、
org.apache.http.client.HttpClient
okhttp3.OkHttpClient
com.squareup.okhttp.OkHttpClient
の順番でクラスが存在するか確認して、見つかったクラスに対応する ClientHttpRequestFactory
が使われることになります。
(注: Spring Boot のバージョン 2.0.2.RELEASE を参照して書いています)
すべて見つからなければ java.net.*
にあるクラスで通信を行う SimpleClientHttpRequestFactory
が使われますが、なんだかんだと依存関係を追加していると、apache の HttpClient
がクラスパスに存在するケースは多いのではないでしょうか。
この HttpClient
、デフォルトの挙動では、通信先から Set-Cookie されたものを次のリクエスト時に Cookie ヘッダにセットして送ろうとします。
Rest API を利用するほとんどのケースでは Cookie を使うことはないと思いますし、うっかり通信先のロードバランサーが StickySession を利用していた場合、特定のリアルサーバーにアクセスが偏ってしまうような弊害も考えられます。
apache HttpClient
を利用する場合は、以下のように disableCookieManagement
することで Cookie を送らなくなります。
HttpClient httpClient = HttpClientBuilder.create()
.disableCookieManagement()
.build();
HttpComponentsClientHttpRequestFactory requestFactory
= new HttpComponentsClientHttpRequestFactory(httpClient);
restTemplate = restTemplateBuilder.requestFactory(() -> requestFactory)
.build();
ちなみに SimpleClientHttpRequestFactory
や OkHttp3 の場合は、特に指定しなくても大丈夫のようです(まもなく Spring Boot もサポートしなくなるので OkHttp2 は未確認です)。
まとめ
RestTemplate
を使う際には、ClientHttpRequestFactory
を指定するのが無難です。
でないとアプリケーションの依存関係が変わることで挙動が意図せず変わる可能性があります。