Skip to content

Usage recipes

Better SSE works with any web-server framework that uses the Node HTTP module or the Fetch API.

This section shows example usage with some popular HTTP libraries.

Feel free to submit a PR with a minimal example for another framework!

server.ts
import { createServer } from "node:http"
import { createSession } from "better-sse"
const server = createServer(async (req, res) => {
switch (req.url) {
case "/sse": {
const session = await createSession(req, res)
session.push("Hello world!")
break
}
default: {
res.writeHead(404).end()
break
}
}
})
server.listen(8080)
server.ts
import { createSecureServer } from "node:http2"
import { createSession } from "better-sse"
const server = createSecureServer({key, cert}, async (req, res) => {
switch (req.url) {
case "/sse": {
const session = await createSession(req, res)
session.push("Hello world!")
break
}
default: {
res.stream.respond({ ":status": 404 })
break
}
}
})
server.listen(8080)
server.ts
import { createResponse } from "npm:better-sse"
Deno.serve({ port: 8080 }, (request) => {
const url = new URL(request.url)
switch (url.pathname) {
case "/sse": {
return createResponse(request, (session) => {
session.push("Hello world!")
})
}
default: {
return new Response("404 Not Found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
})
}
}
})
server.ts
import { createResponse } from "better-sse"
Bun.serve({
port: 8080,
routes: {
"/sse": (req) =>
createResponse(
request,
// Set the keep-alive interval to below
// Bun's default idle timeout of ten (10) seconds
{ keepAlive: 8000 },
(session) => {
session.push("Hello world!")
}
),
},
fetch() {
return new Response("404 Not Found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
})
},
})

Using @mjackson/node-fetch-server as an example of a server framework that implements the Fetch API.

server.ts
import { createServer } from "node:http"
import { createRequestListener, type FetchHandler } from "@mjackson/node-fetch-server"
import { createResponse } from "better-sse"
const handler: FetchHandler = (request) => {
const url = new URL(request.url)
switch (url.pathname) {
case "/sse": {
return createResponse(request, (session) => {
session.push("Hello world!")
})
}
default: {
return new Response("404 Not Found", {
status: 404,
headers: {
"Content-Type": "text/plain",
},
})
}
}
}
const server = createServer(createRequestListener(handler))
server.listen(8080)
server.ts
import express from "express"
import { createSession } from "better-sse"
const app = express()
app.get("/sse", async (req, res) => {
const session = await createSession(req, res)
session.push("Hello world!")
})
app.listen(8080)
server.ts
import Koa from "koa"
import Router from "@koa/router"
import { createSession } from "better-sse"
const app = new Koa()
const router = new Router()
router.get("/sse", async (ctx) => {
// Prevent Koa sending a response and closing the connection
ctx.respond = false
const session = await createSession(ctx.req, ctx.res)
session.push("Hello world!")
})
app.use(router.routes())
app.listen(8080)
server.ts
import { Hono } from "hono"
import { serve } from "@hono/node-server"
import { createResponse } from "better-sse"
const app = new Hono()
app.get("/sse", (c) =>
createResponse(c.req.raw, (session) => {
session.push("Hello world!")
})
)
serve({ fetch: app.fetch, port: 8080 })

Requires first enabling the Node.js compatibility polyfills:

wrangler.jsonc
{
compatibility_flags: ["nodejs_compat"],
compatibility_date: "2024-09-23",
}
index.ts
import { createResponse } from "better-sse"
export default {
async fetch(request, env, ctx): Promise<Response> {
const url = new URL(request.url)
switch (url.pathname) {
case "/sse": {
return createResponse(request, (session) => {
session.push("Hello world!")
})
}
default: {
return new Response("Not Found", {
status: 404,
headers: {
"Content-Type": "text/plain"
},
})
}
}
}
} satisfies ExportedHandler<Env>
app/api/sse/route.ts
import { createResponse } from "better-sse"
export async function GET(request: Request) {
return createResponse(request, (session) => {
session.push("Hello world!")
})
}
pages/api/sse.ts
import { NextApiRequest, NextApiResponse } from "next"
import { createSession } from "better-sse"
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await createSession(req, res)
session.push("Hello world!")
}
server.ts
import { Controller, Get, Req, Res } from "@nestjs/common"
import { Request, Response } from "express"
import { createSession } from "better-sse"
@Controller()
export class SseController {
@Get("sse")
async sse(@Req() req: Request, @Res() res: Response) {
const session = await createSession(req, res)
session.push("Hello world!")
}
}
server.ts
import { Controller, Get, Req, Res } from "@nestjs/common"
import { FastifyReply, FastifyRequest } from "fastify"
import { createSession } from "better-sse"
@Controller()
export class SseController {
@Get("sse")
async sse(@Req() req: FastifyRequest, @Res() res: FastifyReply) {
const session = await createSession(req.raw, res.raw)
session.push("Hello world!")
}
}
server.ts
import Fastify from "fastify"
import { createSession } from "better-sse"
const fastify = Fastify()
fastify.get("/sse", async (request, reply) => {
const session = await createSession(request.raw, reply.raw)
session.push("Hello world!")
})
fastify.listen({ port: 8080 })
app/routes/sse.ts
import { LoaderFunction } from "@remix-run/node"
import { createResponse } from "better-sse"
export const loader: LoaderFunction = ({ request }) =>
createResponse(request, (session) => {
session.push("Hello world!")
})
server.ts
import router from "@adonisjs/core/services/router"
import { createSession } from "better-sse"
router.get("/sse", async ({ request, response }) => {
const session = await createSession(request.request, response.response)
session.push("Hello world!")
})
server.ts
import Hapi from "@hapi/hapi"
import { createSession } from "better-sse"
const init = async () => {
const server = Hapi.server({
port: 8080,
host: "localhost",
})
server.route({
method: "GET",
path: "/sse",
handler: async ({ raw }, { abandon }) => {
const session = await createSession(raw.req, raw.res)
session.push("Hello world!")
// Prevent Hapi from interacting further with the response stream
return abandon
},
})
await server.start()
}
init()