CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-squareup-okhttp3--okhttp-sse

Server-sent events support for OkHttp

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

OkHttp Server-Sent Events (SSE)

OkHttp Server-Sent Events provides experimental support for real-time data streaming using the Server-Sent Events protocol. It enables applications to receive live updates from servers for use cases like chat applications, live feeds, notifications, and monitoring dashboards.

Package Information

  • Package Name: okhttp-sse
  • Package Type: maven
  • Language: Kotlin
  • Coordinates: com.squareup.okhttp3:okhttp-sse
  • Installation: Add implementation 'com.squareup.okhttp3:okhttp-sse:4.12.0' to build.gradle

Core Imports

import okhttp3.sse.EventSource
import okhttp3.sse.EventSourceListener
import okhttp3.sse.EventSources
import okhttp3.OkHttpClient
import okhttp3.Request

For Java:

import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;
import okhttp3.OkHttpClient;
import okhttp3.Request;

Basic Usage

import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.sse.EventSource
import okhttp3.sse.EventSourceListener
import okhttp3.sse.EventSources

// Create HTTP client and event source factory
val client = OkHttpClient()
val factory = EventSources.createFactory(client)

// Create event listener
val listener = object : EventSourceListener() {
    override fun onOpen(eventSource: EventSource, response: Response) {
        println("Connection opened")
    }
    
    override fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) {
        println("Received event: $data")
    }
    
    override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
        println("Connection failed: ${t?.message}")
    }
    
    override fun onClosed(eventSource: EventSource) {
        println("Connection closed")
    }
}

// Create and start event source
val request = Request.Builder()
    .url("https://example.com/events")
    .build()
    
val eventSource = factory.newEventSource(request, listener)

// Clean up resources when done
eventSource.cancel()

Architecture

The OkHttp SSE library follows a factory and listener pattern design:

  • Factory Pattern: EventSources.createFactory() creates event source factories configured with specific OkHttp clients
  • Listener Pattern: EventSourceListener provides callback methods for handling SSE lifecycle events
  • Resource Management: Manual cleanup required via cancel() method
  • Asynchronous Operation: All callbacks occur on background threads
  • OkHttp Integration: Built on OkHttp's robust networking infrastructure with connection pooling and HTTP/2 support

Capabilities

Event Source Factory

Core factory functionality for creating server-sent event connections.

/**
 * Creates a factory for event sources using the provided OkHttpClient.
 * Automatically adds "Accept: text/event-stream" header if not present.
 */
@JvmStatic
fun createFactory(client: OkHttpClient): EventSource.Factory

/**
 * Processes an existing Response as server-sent events.
 * Useful when you already have a Response object from an HTTP call.
 */
@JvmStatic
fun processResponse(response: Response, listener: EventSourceListener)

Event Source Interface

Core interface representing a server-sent event source connection.

interface EventSource {
    /** Returns the original request that initiated this event source */
    fun request(): Request
    
    /** Immediately and violently release resources held by this event source */
    fun cancel()
    
    /** Factory interface for creating new event sources */
    fun interface Factory {
        /** Creates a new event source and immediately returns it */
        fun newEventSource(request: Request, listener: EventSourceListener): EventSource
    }
}

Event Source Listener

Abstract class providing callback methods for handling server-sent event lifecycle.

abstract class EventSourceListener {
    /**
     * Invoked when an event source has been accepted by the remote peer 
     * and may begin transmitting events.
     */
    open fun onOpen(eventSource: EventSource, response: Response) {}
    
    /**
     * Invoked when a server-sent event is received.
     * 
     * Server-sent events have the format:
     * - id: optional unique identifier for the event
     * - event: optional event type name 
     * - data: the actual event payload/message
     * 
     * @param eventSource The event source that received the event
     * @param id Optional event ID from the 'id:' field (null if not specified)
     * @param type Optional event type from the 'event:' field (null if not specified)
     * @param data The event data from the 'data:' field
     */
    open fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) {}
    
    /**
     * Invoked when the event source has been closed normally by the server.
     * No further calls to this listener will be made.
     */
    open fun onClosed(eventSource: EventSource) {}
    
    /**
     * Invoked when an event source has been closed due to an error.
     * Incoming events may have been lost. No further calls to this listener will be made.
     * 
     * @param eventSource The event source that failed
     * @param t The throwable that caused the failure (null for certain types of failures)
     * @param response The HTTP response if available (null for network failures)
     */
    open fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {}
}

Usage Examples

Java Usage

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import okhttp3.sse.EventSources;

// Create client and factory
OkHttpClient client = new OkHttpClient();
EventSource.Factory factory = EventSources.createFactory(client);

// Create listener
EventSourceListener listener = new EventSourceListener() {
    @Override
    public void onOpen(EventSource eventSource, Response response) {
        System.out.println("Connection opened");
    }
    
    @Override
    public void onEvent(EventSource eventSource, String id, String type, String data) {
        System.out.println("Event: " + data);
    }
    
    @Override
    public void onFailure(EventSource eventSource, Throwable t, Response response) {
        System.out.println("Error: " + (t != null ? t.getMessage() : "Unknown"));
    }
    
    @Override
    public void onClosed(EventSource eventSource) {
        System.out.println("Connection closed");
    }
};

// Create event source
Request request = new Request.Builder()
    .url("https://example.com/events")
    .build();
    
EventSource eventSource = factory.newEventSource(request, listener);

// Clean up
eventSource.cancel();

Processing Existing Response

import okhttp3.sse.EventSources

// When you already have a Response object from an HTTP call
val response = client.newCall(request).execute()

// Process the response as SSE
EventSources.processResponse(response, listener)

Custom Headers and Configuration

import java.util.concurrent.TimeUnit

// Add custom headers to the request
val request = Request.Builder()
    .url("https://example.com/events")
    .header("Authorization", "Bearer token")
    .header("Custom-Header", "value")
    .build()

// Configure OkHttp client with custom settings
val client = OkHttpClient.Builder()
    .connectTimeout(30, TimeUnit.SECONDS)
    .readTimeout(60, TimeUnit.SECONDS)
    .build()

val factory = EventSources.createFactory(client)
val eventSource = factory.newEventSource(request, listener)

Error Handling

Common error scenarios and how they're handled:

  • Invalid Content-Type: If the server doesn't return text/event-stream, onFailure is called with the HTTP response
  • Network Errors: Connection issues trigger onFailure with an IOException and null response
  • Malformed SSE Data: Parsing errors cause onFailure to be invoked with parsing exception
  • Normal Closure: Server closes connection normally triggers onClosed (not onFailure)
  • HTTP Errors: Non-2xx status codes trigger onFailure with the error response
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
    when {
        t is IOException && response == null -> {
            println("Network connection error: ${t.message}")
        }
        response != null -> {
            when (response.code) {
                401 -> println("Authentication failed")
                404 -> println("SSE endpoint not found")
                in 400..499 -> println("Client error: ${response.code} ${response.message}")
                in 500..599 -> println("Server error: ${response.code} ${response.message}")
                else -> println("HTTP error: ${response.code} ${response.message}")
            }
        }
        t != null -> println("Parsing or protocol error: ${t.message}")
        else -> println("Unknown error occurred")
    }
}

Threading and Lifecycle

  • All event source operations are asynchronous
  • Callbacks (onOpen, onEvent, onFailure, onClosed) are invoked on background threads
  • Resources must be manually released using cancel() method
  • No automatic reconnection is provided - implement retry logic in your application if needed
  • Event sources do not support pausing or resuming - use cancel() and create new instances

Types

// Core SSE API types
interface EventSource {
    fun request(): Request
    fun cancel()
    
    fun interface Factory {
        fun newEventSource(request: Request, listener: EventSourceListener): EventSource
    }
}

abstract class EventSourceListener {
    open fun onOpen(eventSource: EventSource, response: Response)
    open fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String)
    open fun onClosed(eventSource: EventSource)
    open fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?)
}

object EventSources {
    @JvmStatic fun createFactory(client: OkHttpClient): EventSource.Factory
    @JvmStatic fun processResponse(response: Response, listener: EventSourceListener)
}

// Required OkHttp types (from okhttp3 package)
class OkHttpClient
class Request  
class Response

docs

index.md

tile.json