OkHttp — 定義、機能、HTTPクライアントのアーキテクチャ

著者: IT Sectr 公開日: 2026-03-07 読了時間: 8 分

OkHttpは、Retrofitヨ他のネットワークライブラリの基盤としてSquareが開発した、AndroidヨKotlin向けの高パフォーマンスHTTPクライアントです。効率的なコネクション管理、組み込みキャッシュ、HTTP/2サポートを提供します。Square, 2025によると、OkHttpは世界中のアプリケーションで毎日数十億のリクエストを処理しています。

メインポイント

  • OkHttp — HTTP/2ヨSPDYサポート付き、SquareによるAndroidヨKotlin向けHTTPクライアント
  • コネクションプール — レイテンシを削減するためにTCPコネクションを再利用するメカニズム
  • インターセプタ — InterceptorヨNetworkInterceptorがリクエストヨレスポンスを変更する
  • キャッシュ — 組み込みCacheが繰り返しリクエストのトラフィックを削減する
  • WebSocket — WebSocketプロトコルを通じた双方向通信サポート

OkHttpとは?

OkHttpは、Squareが開発したJava、AndroidヨKotlin向けの効率的なHTTPクライアントです。このライブラリは、HTTP/2、SPDY、WebSocket、およびネットワーク障害時の自動コネクション回復をサポートするHTTPリクエスト実行用の低レベルAPIを提供します。

OkHttpは2013年に、HttpURLConnectionの問題を解決する信頼性の高いHTTPクライアントの必要性に応えて登場しました — コネクションプールの不備、HTTP/2サポートの弱さ、不便なAPI。2025年までにOkHttpはAndroid APIシステムレベルで使用されています: OkHttpはAndroid 4.4 (API 19)以降、HttpURLConnectionの実装に組み込まれています。

Google I/O 2024によると、OkHttpはAndroidエコシステムの全HTTPリクエストの70%以上を処理しています。これは、OkHttpがRetrofit、Apollo GraphQL、Firebaseヨその他多くのライブラリのトランスポート層として機能するためです。開発者は明示的に追加しなくても、OkHttpの機能を自動的に利用できます。

OkHttpの仕組み

OkHttpのアーキテクチャは、インターセプタチェーンに基づいています。各リクエストは、リクエストヨレスポンスを変更できるインターセプタの連続を通過します。このアーキテクチャは、Chain of Responsibilityパターンに類似しており、柔軟な拡張性を可能にします。

アプリケーションがリクエストを送信すると、OkHttpは次のステップを実行します: DNSを解決し、プールからコネクションを選択し、TLSハンドシェークを開き、HTTPリクエストを送信し、レスポンスを受信し、アプリケーションに戻します。RealCallは、リクエストの作成から完了までの全ライフサイクルを管理する内部クラスです。

OkHttpは、リダイレクト(302、301)を自動的に処理し、ネットワーク障害時にリクエストを再実行し、keep-aliveプロトコルに従い、透明なgzip圧縮をサポートします。開発者がこれらの操作のためにコードを書く必要はありません — OkHttpがサーバーヘッダーに基づいて自動的に実行します。

HTTP/2サポートヨマルチプレックス

HTTP/2は、ヘッドオブラインブロッキング(HTTP/1.1の特徴)なしで、単1つのTCPコネクションを通じて一度に複数のリクエストを送信できます。OkHttpは、サーバーがサポートしていれば自動的にHTTP/2を使用し、必要に応じてHTTP/1.1にフォールバックします。

HTTP/2のマルチプレックスは、コネクション構築レイテンシ(TCP + TLS)が100–300ミリ秒になる可能性があるモバイルアプリケーションで特に重要です。10つの並列コネクションの代わりに、OkHttpは1つを使用し、不安定なコネクションのAndroidデバイスで総レイテンシを40–60%削減します。

OkHttpインターセプタ: InterceptorヨNetworkInterceptor

Interceptorは、単1つのメソッドintercept(Chain)をもつインタフェースで、リクエストを受け取り、処理を実行し、レスポンスを戻します。インターセプタには、アプリケーションインターセプタ(addInterceptorで追加)ヨネットワークインターセプタ(addNetworkInterceptor)の2種類があります。

アプリケーションインターセプタは、HTTPリクエストが構築される前に発火します — 原本のリクエストヨ、すべての変換後の最終レスポンスを確認できます。ネットワークインターセプタはネットワークレベルで発火します: gzip圧縮、Content-Lengthヘッダーの追加、リダイレクトヨ再実行後のリクエストを確認できます。レスポンスがキャッシュから提供された場合、ネットワークインターセプタは呼び出されません。

インターセプタの種類追加方法呼び出されるタイミングキャッシュを見る
Application InterceptoraddInterceptor()リクエストの前後はい
Network InterceptoraddNetworkInterceptor()ネットワークレベルいいえ

インターセプタの実践的な使用

実際には、OkHttpのインターセプタは主な3つのタスクを解決します: 認証(Authorizationヘッダーの追加)、ログ(HttpLoggingInterceptorによるデバッグ)、再実行(ネットワーク障害時の自動リクエスト再実行)。複数のインターセプタを組み合わせることで、アプリケーションの各HTTPコールでコードを複製することなく、完全なリクエスト処理パイプラインを構築できます。

インターセプタを追加する順序は重要です: 最初に追加されたInterceptorは、入力時に最初に実行され、出力時に最後に実行されます。NetworkInterceptorの場合、順序はネットワークスタックによって決定されます。推奨される順序: AuthInterceptor(トークンを追加)、LoggingInterceptor(リクエストをログ)、RetryInterceptor(障害時に再実行)。

HttpLoggingInterceptorによるログ

ネットワークリクエストをデバッグするには、HttpLoggingInterceptorが使用されます — Squareによる完成したインターセプタです。メソッド、URL、ヘッダー、リクエストヨレスポンスボディをログに記録します。ロギングレベル: BASIC(メソッド + URL + コード)、HEADERS(ヘッダー付き)、BODY(完全なリクエストヨレスポンス)。BODYは開発中に便利ですが、セキュリティヨパフォーマンスの理由からプロダクションでは無効にされます。

KotlinでのOkHttpコード例

OkHttpを使った基本的なGETリクエストを見てみましょう。まず、OkHttpClientが作成されます — 一度作成されて再利用される重いオブジェクトです。次にURLをもつRequestが構築され、executeを通じて同期的に、またはenqueueを通じて非同期的に実行されます。

kotlin
val client = OkHttpClient.Builder()
    .connectTimeout(15, TimeUnit.SECONDS)
    .readTimeout(15, TimeUnit.SECONDS)
    .build()

val request = Request.Builder()
    .url("https://api.github.com/users/octocat")
    .header("Accept", "application/vnd.github.v3+json")
    .build()

val response = client.newCall(request).execute()
println(response.body()?.string())

非同期実行には、Callbackを受け入れるenqueueメソッドが使用されます。OkHttpはバックグラウンドスレッドでリクエストを実行し、結果を同じスレッドのコールバックに戻します。Androidのメインスレッドに切り替えるには、Handlerまたはコルーチンを使用します。

kotlin
client.newCall(request).enqueue(object : Callback {
    override fun onFailure(
        call: Call, e: IOException
    ) {
        println("リクエストに失敗しました: ${e.message}")
    }

    override fun onResponse(
        call: Call, response: Response
    ) {
        println(response.body()?.string())
    }
})

認証のためのインターセプタの追加

カスタムInterceptorが、各リクエストにBearerトークンを追加します。インターセプタは、Authorizationヘッダーの存在を確認し、トークンがまだ設定されていなければ、ストレッジから追加します。401レスポンスの場合、インターセプタはAuthenticatorを通じてトークンをリフレッシュできます。

kotlin
class AuthInterceptor(
    private val tokenProvider: () -> String?
) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        val token = tokenProvider.invoke()
        val request = originalRequest.newBuilder()
            .header("Authorization", "Bearer $token")
            .build()
        return chain.proceed(request)
    }
}

OkHttpのコネクションプールヨキャッシュ

コネクションプール(ConnectionPool)は、複数のリクエストでTCPコネクションを再利用できるOkHttpの主要な最適化機能です。各リクエストに新しいソケットを作成する代わりに、OkHttpはデフォルトで最大5つの非活動コネクションを5分間保存し、同じホストへの繰り返しリクエストのレイテンシを30–70%削減します。

レスポンスのキャッシュは、Cacheクラスを通じて実装されます。キャッシュを有効にするには、OkHttpClient.Builderでディレクトリヨ最大サイズを指定するだけです。OkHttpは、Cache-Control、Expires、ETagヘッダーに従ってGETレスポンスを自動的にキャッシュし、古くない場合はネットワークリクエストなしでキャッシュされたデータを戻します。

kotlin
val cacheDir = File(context.cacheDir, "http-cache")
val cache = Cache(cacheDir, 10L * 1024 * 1024)

val client = OkHttpClient.Builder()
    .cache(cache)
    .connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES))
    .build()

プールヨキャッシュの適切な設定は、頻繁にリクエストを行うアプリケーション(ニュースフィード、チャット、データ更新)で特に重要です。プールがない場合、各TCPコネクションは3ウェイハンドシェーク(SYN、SYN-ACK、ACK)ヨ可能なTLSハンドシェーク(2–3ラウンドトリップ)が必要となり、各リクエストに100–500ミリ秒が追加されます。

OkHttpは、RealWebSocketクラスを通じてWebSocketもサポートしています。WebSocketコネクションは、HTTPハンドシェーク(101 Switching Protocols)によって確立され、その後双方向プロトコルに切り替わります。OkHttpはコネクションを維持するために自動的にpingフレームを送信し、切断時に再コネクトします。OkHttpのWebSocketは、wss://echo.websocket.orgなどの標準エンドポイントと互換性があります。

OkHttp使用時の一般的な資財

リクエストごとにOkHttpClientを作成することが、もっとも普及した資財です。OkHttpClientには、コネクションプール、キャッシュ、スレッドプールが含まれています。リクエストごとに新しいインスタンスを作成すると、メモリが無駄に消耗されるだけでなく、コネクション再利用のメリットも失われます。OkHttpClientは、DIコンテナを通じてシングルトンにする必要があります。

Response.body()のクローズを忘れると、リソースリークが発生します。ResponseBodyには、読み取り後にクローズする必要があるInputStreamが含まれています。body().string()またはbody().bytes()を使用した場合、OkHttpが自動的にストリームをクローズしますが、body().byteStream()またはbody().charStream()を読む場合は、finallyブロックでclose()を明示的に呼び出す必要があります。

タイムアウト処理の不備ももうひとつの問題です。デフォルトでは、OkHttpのconnectTimeoutは10秒、readTimeoutは10秒、writeTimeoutは10秒です。不安定なコネクションのモバイルアプリケーションでは、connectTimeoutを15–30秒、readTimeoutを15–30秒に設定することをおすすめします。これを行わなければ、信号状態が悪い場合にユーザーが長時間待たされます。

よくある質問

OkHttpとRetrofitの違いは?

OkHttpは、RequestヨResponseを手動で管理する低レベルHTTPクライアントです。Retrofitは、注釈を使用した高レベルの抽象化です。OkHttpはRetrofitのトランスポート層として使用されますが、追加のライブラリなしで単独で動作することもできます。

OkHttpはHTTPSをどのように処理しますか?

OkHttpは、TLSハンドシェークにSSLSocketFactoryを使用します。このライブラリは、証明書ピンニング用のCertificatePinner、カスタム検証用のTrustManager、および証明書に対するホスト名を検証するHostnameVerifierをサポートしています。

OkHttpでネットワークエラーを捕捉するには?

同期リクエストは、ネットワーク問題が起きた場合にIOExceptionをスローします。非同期リクエストは、IOExceptionをもつonFailureコールを受け取ります。HTTPエラー(4xx、5xx)の場合、レスポンスは成功とみなされます — エラーコードはresponse.isSuccessful()で確認します。

OkHttpはWebSocketをサポートしていますか?

はい、OkHttpにはWebSocketクラスヨWebSocketListenerを通じた組み込みのWebSocketサポートがあります。コネクション確立後、WebSocketは繰り返しHTTPリクエストなしでリアルタイムにメッセージを送信ヨ受信できます。

OkHttpでリダイレクトを無効にするには?

OkHttpClient.BuilderでfollowRedirects(false)followSslRedirects(false)を使用して自動リダイレクトを無効にします。これは、リダイレクトURLからトークンを抽出する等、リダイレクトを手動で処理したい場合に便利です。

まとめ

  • OkHttp — HTTP/2ヨSPDYサポート付き、Squareによる高パフォーマンスHTTPクライアント
  • インターセプタアーキテクチャがリクエスト変更のためにChain of Responsibilityを実装
  • コネクションプールがTCPコネクションを再利用し、レイテンシを30–70%削減
  • キャッシュ Cache-ControlヨETagが繰り返しリクエストのトラフィックを削減
  • WebSocketがリアルタイムの双方向通信を実現
  • OkHttpClientはシングルトンにする必要 — リクエストごとの作成はリークの原因
  • ResponseBodyはbyteStreamでの読み取り時に明示的なクローズが必要

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください