Server-Sent Events (SSE) Set up on Server and Client End

SSE, or Server-Sent Events, is a web technology that allows a server to push real-time, one-way updates to a client (usually a web browser) over a single, long-lived HTTP connection. It’s ideal for scenarios where the client needs to receive continuous streams of data, like stock tickers, live sports scores, or news feeds, without constantly polling the server.

The counterpart to real-time streaming (like SSE or WebSockets) is polling (or more specifically, long polling for a slightly more “real-time” feel than simple polling), which is the traditional model of HTTP communication. It’s worth noting WebSockets is also real-time streaming but bidirectional.

Server-Side Python Example (using Flask)

This example uses the Flask web framework to create a simple SSE endpoint.

import time
from flask import Flask, Response, render_template_string

app = Flask(__name__)

# A simple HTML page to host our SSE client
HTML_PAGE = """
<!DOCTYPE html>
<html>
<head>
    <title>SSE Client</title>
</head>
<body>
    <h1>Server-Sent Events Example</h1>
    <div id="messages"></div>

    <script>
        const eventSource = new EventSource('/event_stream');
        const messagesDiv = document.getElementById('messages');

        eventSource.onopen = function() {
            console.log("SSE connection opened.");
            const p = document.createElement('p');
            p.textContent = "Connection established.";
            messagesDiv.appendChild(p);
        };

        eventSource.onmessage = function(event) {
            console.log("Received message:", event.data);
            const p = document.createElement('p');
            p.textContent = `Message from server: ${event.data}`;
            messagesDiv.appendChild(p);
        };

        eventSource.onerror = function(error) {
            console.error("EventSource failed:", error);
            const p = document.createElement('p');
            p.textContent = `Error: ${error.message || 'Unknown error'}`;
            messagesDiv.appendChild(p);
            eventSource.close(); // Close on error, EventSource might try to reconnect
        };

        eventSource.addEventListener('custom_event', function(event) {
            console.log("Received custom event:", event.data);
            const p = document.createElement('p');
            p.textContent = `Custom event from server: ${event.data}`;
            messagesDiv.appendChild(p);
        });

        // Optional: Listen for the 'close' event (not standard EventSource, but useful for debugging)
        // eventSource.addEventListener('close', function() {
        //     console.log("SSE connection closed.");
        // });

    </script>
</body>
</html>
"""

@app.route('/')
def index():
    return render_template_string(HTML_PAGE)

@app.route('/event_stream')
def event_stream():
    def generate_events():
        i = 0
        while True:
            # Send a regular message
            data = f"Server time: {time.ctime()} (message {i})"
            yield f"data: {data}\n\n"
            print(f"Sent: {data}")

            # Send a custom event every 3 messages
            if i % 3 == 0 and i > 0:
                custom_data = f"This is a custom event {i/3}"
                yield f"event: custom_event\ndata: {custom_data}\n\n"
                print(f"Sent custom_event: {custom_data}")

            i += 1
            time.sleep(2) # Send an event every 2 seconds

    return Response(generate_events(), mimetype='text/event-stream')

if __name__ == '__main__':
    # Run the Flask app. You can access it at http://127.0.0.1:5000/
    # The SSE stream will be available at http://127.0.0.1:5000/event_stream
    app.run(debug=True, port=5000)

In this example, '/event_stream' is the SSE URL.

Client-Side Python Example (using requests and sseclient)

While SSE is primarily designed for browser clients, you can also consume SSE streams from Python using libraries. The requests library is good for basic HTTP, but for SSE, sseclient is more suitable as it handles the event parsing and connection management.

import requests
from sseclient import SSEClient # You might need to install this: pip install sseclient

# The SSE URL from our Flask example (assuming it's running)
SSE_URL = "http://127.0.0.1:5000/event_stream"

print(f"Connecting to SSE URL: {SSE_URL}")

try:
    # Create an SSEClient instance
    # The 'stream=True' is crucial for requests to keep the connection open
    messages = SSEClient(SSE_URL)

    # Iterate over the incoming messages
    for msg in messages:
        # Each 'msg' object has attributes like 'data', 'event', 'id', 'retry'
        print(f"Received (event: {msg.event}): {msg.data}")

        # You can also check for specific event types
        if msg.event == 'custom_event':
            print(f"  --> This was a CUSTOM EVENT: {msg.data}")

except requests.exceptions.ConnectionError as e:
    print(f"Error connecting to SSE server: {e}")
    print("Make sure the Flask SSE server (sse_server.py) is running.")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

print("Client finished.")

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.