Apache HttpComponents (HttpClient)の圧縮通信サポート状況 (gzip)

投稿者 : OSCA

[PR] 関東地方の美しい夜景を観にいこう。 夜景サイト「夜景散歩」で夜景スポットを検索

 本稿では The Apache Software Foundation で開発されているHTTP通信ライブラリ「Apache HttpComponents」(旧 HttpClient)を用いて gzip などで圧縮されたコンテンツをレスポンスとして受け取りたい場合の情報を整理します。

実現したいこと

 まずは実現したいことを整理してみましょう。 ここでやりたいことは、次のように整理できます。

  1. Apache HttpClient からHTTPリクエストヘッダ Accept-Encoding を送信したい。
  2. HTTP レスポンスヘッダの Context-Type で gzip などが返却された場合、圧縮されたコンテンツを受信したい。

 クライアントとサーバーの両方が圧縮通信に対応していれば、ネットワークトラフィック量を減らすことができますね。 (この点について詳しい解説が必要な場合は別稿「HTTPリクエストヘッダ Accept-Encoding とは?」をご覧ください)

Apache HttpClient 4.3 以降

 2017年12月現在、最新の HttpClient はバージョン 4.5.4 ですが、Apache HttpClient 4.3 以降を利用するようにすれば、Context-Type ヘッダの値などを気にせずにクラスが自動的に対応をしてくれるようになりました。 それまで一般的に利用されていた DefaultHttpClient クラスが deprecated (非推奨)に変更され、次の例のように HttpClientBuilder クラスを利用して HttpClient をインスタンス化することが推奨されました。 その HttpClientBuilder が返却する HttpClient クラスが圧縮通信に対応しています。

CloseableHttpClient httpClient = HttpClientBuilder.create().build();

Apache HttpClient 4.2

 Apache HttpClient 4.2 を利用している場合、4.2 で DecompressingHttpClient というクラスが追加されていますので、それを利用するのが良さそうです。 それまで一般的に利用されていた DefaultHttpClient クラスでは圧縮通信に対応していませんでしたが、DecompressingHttpClient クラスで圧縮通信に対応しました。 DecompressingHttpClient クラスは Content-Encoding の判定などもクラス内で隠蔽してくれているので、クラスを利用する際に何か特別気にする必要はありません。

HttpClient httpCLient = new DecompressingHttpClient(new DefaultHttpClient());

 ただし、この DecompressingHttpClient クラスのコンストラクタも 4.3 で deprecated になっています。

4.2 以前

 Apache HttpClient 4.2 以前のバージョンを利用している場合は、次のサンプルコードのように、自前で Content-Type の判定とコンテンツの解凍処理を実装する必要がありました。

// Apache HttpClient 4.1 の例
Header[] contentEncodingHeaders = httpResponse.getHeaders("Content-Encoding");
if( contentEncodingHeaders[0].getValue().contains("gzip") ) {
    try(
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        InputStream responseStream = new GZIPInputStream(httpResponse.getEntity().getContent());
    ) {
        byte[] buffer = new byte[4096];
        int length;
        while((length=responseStream.read(buffer))>0){
            outStream.write(buffer,0,length);
        }
        System.out.println(new String(outStream.toByteArray()));
    }
    catch(Exception exception) {
        throw exception;
    }
}

おわりに

 Apache HttpComponents は、アップデートのたびにクラスインターフェースが大きく変更されてわかりにくいので、ここでは圧縮通信のサポート状況について整理してみました。 何かのお役に立てれば幸いです。

Java環境構築へ戻る

Javaのトップへ戻る

著者 : OSCA

OSCA

Java, PHP 系のWEBエンジニア。 WEBエンジニア向けコミュニティ「WEBエンジニア勉強会」を主催。 個人として何か一つでも世の中の多くの人に使ってもらえるものを作ろうと日々奮闘中。
@engineer_osca