or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

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

Server-sent events support for OkHttp

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/com.squareup.okhttp3/okhttp-sse@4.12.x

To install, run

npx @tessl/cli install tessl/maven-com-squareup-okhttp3--okhttp-sse@4.12.0

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