Niraj Chauhan

Niraj Chauhan

#father #husband #SoftwareCraftsman #foodie #gamer #OnePiece #naruto

Exploring Server-Sent Events (SSE) with NestJS

Posted by on

Server-Sent Events (SSE) offer a robust standard for enabling web servers to push real-time updates directly to the client’s web browser. Unlike WebSockets, which facilitate full-duplex communication, SSE specializes in one-way communication from the server to the client. This architecture is particularly advantageous for broadcasting server-originated updates such as live news feeds, social media updates, or sports scores. The progressive Node.js framework, NestJS, robustly supports SSE, enhancing the management of real-time data in a scalable fashion.

Architect drawing

SSE comes with several key features that enhance its reliability for real-time communication. For instance, it supports automatic reconnection in case the connection drops, and utilizes message IDs to maintain the integrity of the message sequence. Furthermore, SSE operates over the HTTP protocol, which simplifies implementation and reduces overhead compared to WebSockets. This makes SSE an excellent choice for applications requiring server-to-client communication only. NestJS leverages these advantages, providing developers with integrated tools and methods to manage connections and data flow seamlessly.

Consider the process of ChatGPT responding to queries in real-time—not through WebSockets, but via SSE. When a request is made, the server opens a stream and begins transmitting data chunks or events. The client, upon receiving these events, can render them accordingly. This interaction still utilizes the HTTP protocol, adhering to its conventional structure and simplicity.

Implementing SSE in NestJS is streamlined through the use of RXJS. Developers can create an observable stream where messages are emitted. At the controller level, this stream is subscribed to, and each chunk of data received is written directly to the response stream, maintaining a continuous flow of data.

The format of SSE messages is crucial for correct parsing by the client. Each message begins with “event:” followed by the event name and a newline character (\n). The next line starts with “data:” followed by the message content—whether text, a JSON object, or any other data type. The message concludes with two newline characters, signaling the end of the message.

Here’s what a typical SSE message looks like:

event: chunk\ndata: message\n\n

Or

event: chunk
data: message

Below is a practical example of how to implement SSE in a NestJS controller:

import { Body, Controller, Header, HttpCode, Post, Res } from "@nestjs/common";
import { Observable } from 'rxjs';
import { Response } from "express";

@Controller("/api")
export class AppController {
  @Post("/chat")
  @HttpCode(200)
  @Header("Content-Type", "text/event-stream")
  @Header("Cache-Control", "no-cache")
  @Header("Connection", "keep-alive")
  @Header("Transfer-Encoding", "chunked")
  chat(@Res() res: Response): void {
    const chatObservable = new Observable<string>((observer) => {
      const interval = setInterval(() => {
        observer.next(`event: chunk\ndata: The random number is: ${Math.random()}\n\n`);
      }, 1000);
      setTimeout(() => {
        clearInterval(interval);
        observer.complete();
      }, 6000);
    });

    chatObservable.subscribe({
      next: (event) => res.write(event),
      error: (err) => res.end(err),
      complete: () => res.end()
    });
  }
}

This example showcases how NestJS, combined with Server-Sent Events, can be utilized to build efficient and real-time web applications, making it an invaluable tool for modern web development.

It’s also important to ensure that the correct headers are being passed with each response. The Content-Type should be set to text/event-stream to properly instruct the client on how to handle the incoming stream. Additional headers such as Cache-Control, Connection, and Transfer-Encoding play critical roles in maintaining the connection’s integrity and performance. Proper configuration of these headers is crucial for the seamless operation and reliability of SSE.