OkHttp es un cliente HTTP de alto rendimiento para Android y Kotlin, desarrollado por Square como base para Retrofit y otras bibliotecas de red. Proporciona una gestión eficiente de conexiones, almacenamiento en caché integrado y soporte para HTTP/2. Según Square, 2025, OkHttp maneja miles de millones de solicitudes diariamente en aplicaciones de todo el mundo.
Puntos clave
OkHttp es un cliente HTTP eficiente para Java, Android y Kotlin, desarrollado por Square. La biblioteca proporciona una API de bajo nivel para ejecutar solicitudes HTTP con soporte para HTTP/2, SPDY, WebSocket y recuperación automática de conexiones en fallos de red.
OkHttp surgió en 2013 como respuesta a la necesidad de un cliente HTTP fiable que solucionara los problemas de HttpURLConnection: falta de grupo de conexiones, soporte débil de HTTP/2 y una API incómoda. Para 2025, OkHttp se utiliza a nivel de sistema en Android API: OkHttp está integrado en la implementación de HttpURLConnection desde Android 4.4 (API 19).
Según Google I/O 2024, OkHttp maneja más del 70% de todas las solicitudes HTTP en el ecosistema Android. Esto es posible porque OkHttp actúa como capa de transporte para Retrofit, Apollo GraphQL, Firebase y muchas otras bibliotecas. Los desarrolladores obtienen la funcionalidad de OkHttp automáticamente sin necesidad de agregarlo explícitamente.
Arquitectura de OkHttp se basa en una cadena de interceptores. Cada solicitud pasa a través de una secuencia de interceptores que pueden modificar la Request, la Response o interrumpir la ejecución. Esta arquitectura se asemeja al patrón Chain of Responsibility y permite una extensibilidad flexible.
Cuando una aplicación envía una solicitud, OkHttp realiza los siguientes pasos: resuelve DNS, selecciona una conexión del grupo (o crea una nueva), abre un handshake TLS (si es HTTPS), envía la solicitud HTTP, recibe la respuesta y la devuelve a la aplicación. RealCall es la clase interna que gestiona el ciclo de vida completo de una solicitud desde su creación hasta su finalización.
OkHttp maneja automáticamente las redirecciones (302, 301), reintenta solicitudes en fallos de red, sigue el protocolo keep-alive y admite compresión gzip transparente. El desarrollador no necesita escribir código para estas operaciones: OkHttp las realiza automáticamente según las cabeceras del servidor.
HTTP/2 permite enviar múltiples solicitudes a través de una única conexión TCP simultáneamente, sin bloqueo head-of-line (característico de HTTP/1.1). OkHttp utiliza automáticamente HTTP/2 si el servidor lo admite, y cambia de forma transparente a HTTP/1.1 cuando es necesario.
La multiplexación HTTP/2 es especialmente importante para aplicaciones móviles, donde la latencia de establecimiento de conexión (TCP + TLS) puede ser de 100–300 ms. En lugar de 10 conexiones secuenciales, OkHttp utiliza una, reduciendo la latencia total en un 40–60% en dispositivos Android típicos con conexiones inestables.
Interceptor es una interfaz con un único método intercept(Chain), que recibe una Request, realiza acciones y devuelve una Response. Hay dos tipos de interceptores: interceptores de aplicación (agregados mediante addInterceptor) e interceptores de red (addNetworkInterceptor).
Los interceptores de aplicación se ejecutan antes de que se forme la solicitud HTTP: ven la Request original y la Response final después de todas las transformaciones. Los interceptores de red se ejecutan a nivel de red: ven la solicitud después de la compresión gzip, la adición de cabeceras Content-Length, las redirecciones y los reintentos. Los interceptores de red no se llaman si la respuesta se sirve desde la caché.
| Tipo de interceptor | Método de adición | Cuándo se llama | Ve la caché |
|---|---|---|---|
| Application Interceptor | addInterceptor() | Antes y después de la solicitud | Sí |
| Network Interceptor | addNetworkInterceptor() | A nivel de red | No |
En la práctica, los interceptores de OkHttp resuelven tres tareas principales: autorización (agregar la cabecera Authorization), registro (HttpLoggingInterceptor para depuración) y reintento (repetición automática de solicitudes en fallos de red). Combinando varios interceptores, se puede construir un pipeline completo de procesamiento de solicitudes sin duplicar código en cada llamada HTTP de la aplicación.
El orden de agregar interceptores importa: el Interceptor agregado primero se ejecuta primero a la entrada y último a la salida. Para NetworkInterceptor, el orden lo determina la pila de red. Orden recomendado: AuthInterceptor (agrega token), LoggingInterceptor (registra la solicitud), RetryInterceptor (reintenta en fallos).
Para depurar solicitudes de red, se utiliza HttpLoggingInterceptor, un interceptor listo para usar de Square. Registra el método, la URL, las cabeceras y el cuerpo de la solicitud y la respuesta. Niveles de registro: BASIC (método + URL + código), HEADERS (con cabeceras) y BODY (solicitud y respuesta completos). BODY es útil durante el desarrollo, pero se desactiva en producción por razones de seguridad y rendimiento.
Veamos una solicitud GET básica usando OkHttp. Primero se crea un OkHttpClient, un objeto pesado que se crea una vez y se reutiliza. Luego se forma una Request con una URL, y la solicitud se ejecuta de forma síncrona mediante execute o asíncrona mediante enqueue.
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())
Para la ejecución asíncrona, se utiliza el método enqueue, que acepta un Callback. OkHttp ejecuta la solicitud en un hilo en segundo plano y devuelve el resultado en el callback en el mismo hilo. Para cambiar al hilo principal de Android, use Handler o corrutinas.
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("Solicitud fallida: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
Un Interceptor personalizado agrega un token Bearer a cada solicitud. El interceptor verifica la presencia de la cabecera Authorization y, si el token aún no está configurado, lo agrega desde el almacenamiento. En una respuesta 401, el interceptor puede actualizar el token mediante Authenticator.
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)
}
}
Grupo de conexiones (ConnectionPool) es una optimización clave de OkHttp que permite reutilizar conexiones TCP para múltiples solicitudes. En lugar de crear un nuevo socket para cada solicitud, OkHttp almacena hasta 5 conexiones inactivas (por defecto) durante 5 minutos, reduciendo la latencia en un 30–70% para solicitudes repetidas al mismo host.
El almacenamiento en caché de respuestas se implementa mediante la clase Cache. Para habilitar la caché, basta con especificar el directorio y el tamaño máximo en OkHttpClient.Builder. OkHttp almacena en caché automáticamente las respuestas GET según las cabeceras Cache-Control, Expires y ETag, devolviendo datos en caché sin solicitud de red si no están desactualizados.
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()
La configuración adecuada del grupo y la caché es especialmente importante para aplicaciones con solicitudes frecuentes: feeds de noticias, chats, actualizaciones de datos. Sin grupo, cada conexión TCP requiere un handshake de tres vías (SYN, SYN-ACK, ACK) y potencialmente un handshake TLS (2–3 rondas), añadiendo 100–500 ms a cada solicitud.
OkHttp también admite WebSocket mediante la clase RealWebSocket. Una conexión WebSocket se establece a través de un handshake HTTP (101 Switching Protocols) y luego cambia a un protocolo bidireccional. OkHttp envía automáticamente tramas ping para mantener la conexión activa y se reconecta en caso de desconexión. El WebSocket de OkHttp es compatible con endpoints estándar como wss://echo.websocket.org.
Crear OkHttpClient para cada solicitud es el error más común. OkHttpClient contiene un grupo de conexiones, caché y grupo de hilos. Crear una nueva instancia para cada solicitud no solo desperdicia memoria, sino que también pierde el beneficio de la reutilización de conexiones. OkHttpClient debe ser un singleton mediante un contenedor DI.
Ignorar el cierre de Response.body() provoca fugas de recursos. ResponseBody contiene un InputStream que debe cerrarse después de la lectura. Si se usa body().string() o body().bytes(), OkHttp cierra el flujo automáticamente, pero al leer body().byteStream() o body().charStream(), se requiere una llamada explícita a close() en un bloque finally.
Falta de manejo de Timeout es otro problema. Por defecto, OkHttp tiene connectTimeout de 10 segundos, readTimeout de 10 segundos y writeTimeout de 10 segundos. Para aplicaciones móviles con conexiones inestables, se recomienda establecer connectTimeout de 15–30 segundos y readTimeout de 15–30 segundos, de lo contrario el usuario esperará demasiado con una señal deficiente.
Preguntas frecuentes
OkHttp es un cliente HTTP de bajo nivel con gestión manual de Request y Response. Retrofit es una abstracción de alto nivel con anotaciones. OkHttp se utiliza como capa de transporte para Retrofit, pero también puede funcionar de forma independiente sin bibliotecas adicionales.
OkHttp utiliza SSLSocketFactory para el handshake TLS. La biblioteca admite CertificatePinner para fijación de certificados, TrustManager para validación personalizada y HostnameVerifier para verificar el nombre del host contra el certificado.
Las solicitudes síncronas lanzan IOException en problemas de red. Las solicitudes asíncronas reciben una llamada onFailure con IOException. Para errores HTTP (4xx, 5xx), la respuesta se considera exitosa: el código de error se verifica mediante response.isSuccessful().
Sí, OkHttp tiene soporte integrado para WebSocket mediante la clase WebSocket y WebSocketListener. Después de establecer una conexión, WebSocket permite enviar y recibir mensajes en tiempo real sin solicitudes HTTP repetidas.
Deshabilite las redirecciones automáticas mediante followRedirects(false) y followSslRedirects(false) en OkHttpClient.Builder. Esto es útil cuando necesita manejar manualmente una redirección, por ejemplo, para extraer un token de la URL de redirección.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también