|
| 1 | +--- |
| 2 | +layout: ../../../layouts/Base.astro |
| 3 | +title: Custom connection adapters |
| 4 | +description: Learn how to use custom connection adapters to make Better SSE compatible with anything. |
| 5 | +--- |
| 6 | + |
| 7 | +*Connection adapters* allow you to make Better SSE [sessions](/better-sse/reference/api/#sessionstate) compatible with any protocol, framework or runtime environment. |
| 8 | + |
| 9 | +Where *sessions* manage the request and response lifecycle, the formatting of data and other SSE-specific behaviour, [*connection adapters*](/better-sse/reference/api/#connection) implement the underlying connection itself, such as extracting request headers and query parameters, sending response headers and data chunks and reporting when the connection closes. |
| 10 | + |
| 11 | +## Built-in connection adapters |
| 12 | + |
| 13 | +Better SSE ships with a number of built-in connection adapters that are used internally but can also be extended to add or augment functionality. |
| 14 | + |
| 15 | +When a session is created, it will automatically determine which connection adapter to use based on the arguments provided. |
| 16 | + |
| 17 | +### Fetch API |
| 18 | + |
| 19 | +When providing an instance of [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) (and optionally [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response)) from the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API). The following example with [Hono](https://hono.dev/): |
| 20 | + |
| 21 | +```typescript |
| 22 | +import { createResponse } from "better-sse" |
| 23 | + |
| 24 | +app.get("/sse", async (c) => |
| 25 | + createResponse(c.req.raw, (session) => { |
| 26 | + session.push("Hello world!") |
| 27 | + }) |
| 28 | +) |
| 29 | +``` |
| 30 | + |
| 31 | +Causes the session to use the built-in [`FetchConnection`](/better-sse/reference/api/#fetchconnection) adapter, equivalent to the following: |
| 32 | + |
| 33 | +```typescript |
| 34 | +import { createResponse, FetchConnection } from "better-sse" |
| 35 | + |
| 36 | +app.get("/sse", async (c) => { |
| 37 | + const connection = new FetchConnection(c.req.raw, null) |
| 38 | + |
| 39 | + return createResponse(connection, (session) => { |
| 40 | + session.push("Hello world!") |
| 41 | + }) |
| 42 | +}) |
| 43 | +``` |
| 44 | + |
| 45 | +### Node HTTP/1 API |
| 46 | + |
| 47 | +When providing instances of [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) and [`ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) from the [Node HTTP/1 API](https://nodejs.org/api/http.html). The following example with [Express](https://expressjs.com/): |
| 48 | + |
| 49 | +```typescript |
| 50 | +import { createSession } from "better-sse" |
| 51 | + |
| 52 | +app.get("/sse", async (req, res) => { |
| 53 | + const session = await createSession(req, res) |
| 54 | + session.push("Hello world!") |
| 55 | +}) |
| 56 | +``` |
| 57 | + |
| 58 | +Causes the session to use the built-in [`NodeHttp1Connection`](/better-sse/reference/api/#nodehttp1connection) adapter, equivalent to the following: |
| 59 | + |
| 60 | +```typescript |
| 61 | +import { createSession, NodeHttp1Connection } from "better-sse" |
| 62 | + |
| 63 | +app.get("/sse", async (req, res) => { |
| 64 | + const connection = new NodeHttp1Connection(req, res) |
| 65 | + const session = await createSession(connection) |
| 66 | + session.push("Hello world!") |
| 67 | +}) |
| 68 | +``` |
| 69 | + |
| 70 | +### Node HTTP/2 Compatibility API |
| 71 | + |
| 72 | +When providing instances of [`Http2ServerRequest`](https://nodejs.org/api/http2.html#class-http2http2serverrequest) and [`Http2ServerResponse`](https://nodejs.org/api/http2.html#class-http2http2serverresponse) from the [Node HTTP/2 Compatibility API](https://nodejs.org/api/http2.html#compatibility-api). The following example with [`createServer`](https://nodejs.org/api/http2.html#http2createserveroptions-onrequesthandler): |
| 73 | + |
| 74 | +```typescript |
| 75 | +import { createSession } from "better-sse" |
| 76 | + |
| 77 | +createServer(async (req, res) => { |
| 78 | + const { ":path": path, ":method": method } = req.headers |
| 79 | + |
| 80 | + if (req.url === "/sse") { |
| 81 | + const session = await createSession(req, res) |
| 82 | + session.push("Hello world!") |
| 83 | + } |
| 84 | +}) |
| 85 | +``` |
| 86 | + |
| 87 | +Causes the session to use the built-in [`NodeHttp2CompatConnection`](/better-sse/reference/api/#nodehttp2compatconnection) adapter, equivalent to the following: |
| 88 | + |
| 89 | +```typescript |
| 90 | +import { createSession, NodeHttp2CompatConnection } from "better-sse" |
| 91 | + |
| 92 | +createServer(async (req, res) => { |
| 93 | + const { ":path": path, ":method": method } = req.headers |
| 94 | + |
| 95 | + if (req.url === "/sse") { |
| 96 | + const connection = new NodeHttp2CompatConnection(req, res) |
| 97 | + const session = await createSession(connection) |
| 98 | + session.push("Hello world!") |
| 99 | + } |
| 100 | +}) |
| 101 | +``` |
| 102 | + |
| 103 | +## Create a custom connection adapter |
| 104 | + |
| 105 | +You can create a custom connection adapter from scratch - extending from the [`Connection` class](/better-sse/reference/api/#connection) directly - or use any of the in-built adapters as a base: |
| 106 | + |
| 107 | +* [`FetchConnection`](/better-sse/reference/api/#fetchconnection) ([source code](https://github.com/MatthewWid/better-sse/blob/master/src/adapters/FetchConnection.ts)) |
| 108 | +* [`NodeHttp1Connection`](/better-sse/reference/api/#nodehttp1connection) ([source code](https://github.com/MatthewWid/better-sse/blob/master/src/adapters/NodeHttp1Connection.ts)) |
| 109 | +* [`NodeHttp2CompatConnection`](/better-sse/reference/api/#nodehttp2compatconnection) ([source code](https://github.com/MatthewWid/better-sse/blob/master/src/adapters/NodeHttp2CompatConnection.ts)) |
| 110 | + |
| 111 | +### Koa |
| 112 | + |
| 113 | +Let's create a custom connection adapter that abstracts away the implementation details of SSE streaming with [Koa](https://koajs.com/). |
| 114 | + |
| 115 | +To begin, create a class that extends from the base [`Connection` class](/better-sse/reference/api/#connection): |
| 116 | + |
| 117 | +```typescript title="KoaConnection.ts" |
| 118 | +import { Connection } from "better-sse" |
| 119 | + |
| 120 | +class KoaConnection extends Connection {} |
| 121 | +``` |
0 commit comments