eventsource-client 0.17.0

Client for the Server-Sent Events protocol (aka EventSource)
Documentation

eventsource-client

Run CI

Client for the Server-Sent Events protocol (aka EventSource).

This library provides a complete SSE protocol implementation with a built-in HTTP transport powered by hyper v1. The pluggable transport design also allows you to use your own HTTP client (reqwest, custom, etc.) if needed.

Quick Start

1. Add dependencies

[dependencies]
eventsource-client = { version = "0.17", features = ["hyper-rustls-native-roots"] }
futures = "0.3"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Features:

  • hyper - Enables the built-in HyperTransport for HTTP support (enabled by default)
  • hyper-rustls-native-roots, hyper-rustls-webpki-roots, or native-tls - Adds HTTPS support via rustls (optional)

2. Use the client

use eventsource_client::{ClientBuilder, SSE};
use launchdarkly_sdk_transport::HyperTransport;
use futures::TryStreamExt;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create HTTP transport with timeouts
    let transport = HyperTransport::builder()
        .connect_timeout(Duration::from_secs(10))
        .read_timeout(Duration::from_secs(30))
        .build_https();  // or .build_http() for plain HTTP

    // Build SSE client
    let client = ClientBuilder::for_url("https://example.com/stream")?
        .header("Authorization", "Bearer token")?
        .build_with_transport(transport);

    // Stream events
    let mut stream = client.stream();

    while let Some(event) = stream.try_next().await? {
        match event {
            SSE::Event(evt) => println!("Event: {}", evt.event_type),
            SSE::Comment(c) => println!("Comment: {}", c),
            SSE::Connected(_) => println!("Connected!"),
        }
    }

    Ok(())
}

Example

The tail example demonstrates a complete SSE client using the built-in HyperTransport:

Run with HTTP:

cargo run --example tail --features hyper -- http://live-test-scores.herokuapp.com/scores "Bearer token"

Run with HTTPS:

cargo run --example tail --features hyper-rustls-native-roots -- https://live-test-scores.herokuapp.com/scores "Bearer token"
cargo run --example tail --features hyper-rustls-webpki-roots -- https://live-test-scores.herokuapp.com/scores "Bearer token"
cargo run --example tail --features native-tls -- https://live-test-scores.herokuapp.com/scores "Bearer token"

The example shows:

  • Creating a HyperTransport with custom timeouts
  • Building an SSE client with authentication headers
  • Configuring automatic reconnection with exponential backoff
  • Handling different SSE event types (events, comments, connection status)
  • Proper error handling for HTTPS URLs without the hyper-rustls-native-roots feature

See examples/tail.rs for the complete implementation.

Features

  • Built-in HTTP transport - Production-ready HyperTransport powered by hyper v1
  • Configurable timeouts - Connect, read, and write timeout support
  • HTTPS support - Optional rustls integration via the hyper-rustls-* or native-tls features
  • Pluggable transport - Use a custom HTTP client if needed (reqwest, etc.)
  • Tokio-based streaming - Efficient async/await support
  • Custom headers - Full control over HTTP requests
  • Automatic reconnection - Configurable exponential backoff
  • Retry logic - Handle transient failures gracefully
  • Redirect following - Automatic handling of HTTP redirects
  • Last-Event-ID - Resume streams from last received event

Custom HTTP Transport

While the built-in HyperTransport works for most use cases, you can implement the HttpTransport trait to use your own HTTP client:

use launchdarkly_sdk_transport::{HttpTransport, Request, ResponseFuture};
use bytes::Bytes;

#[derive(Clone)]
struct MyTransport {
    // Your HTTP client here
}

impl HttpTransport for MyTransport {
    fn request(&self, request: Request<Option<Bytes>>) -> ResponseFuture {
        // Implement HTTP request handling
        // See the HttpTransport trait documentation for details
        todo!()
    }
}

This allows you to:

  • Use a different HTTP client (reqwest, custom, etc.)
  • Implement custom connection pooling or proxy logic
  • Add specialized middleware or observability

Architecture

┌─────────────────────────────────────┐
│   Your Application                  │
└─────────────┬───────────────────────┘
              │
              ▼
┌─────────────────────────────────────┐
│   eventsource-client                │
│   (SSE Protocol Implementation)     │
└─────────────┬───────────────────────┘
              │ HttpTransport trait
              ▼
┌─────────────────────────────────────┐
│   HTTP Transport Layer              │
│   • HyperTransport (built-in)       │
│   • Custom (reqwest, etc.)          │
└─────────────────────────────────────┘

Stability

This library is actively maintained. The SSE protocol implementation is stable. Breaking changes follow semantic versioning.