|
16 | 16 | - [Async operations](#async-operations)
|
17 | 17 | - [Debugging Koa](#debugging-koa)
|
18 | 18 | - [HTTP2](#http2)
|
| 19 | + - [Server-Side Events](#server-side-events) |
19 | 20 |
|
20 | 21 | ## Writing Middleware
|
21 | 22 |
|
@@ -267,3 +268,48 @@ const serverOptions = {
|
267 | 268 |
|
268 | 269 | const server = http2.createSecureServer(serverOptions, onRequestHandler);
|
269 | 270 | ```
|
| 271 | + |
| 272 | +## Server-Side Events |
| 273 | + |
| 274 | +An example of using server-side events with Koa: |
| 275 | + |
| 276 | +```js |
| 277 | +import PassThrough from 'stream' |
| 278 | +import OpenAI from 'openai' |
| 279 | +import Koa from 'koa' |
| 280 | + |
| 281 | +const openai = new OpenAI({ |
| 282 | + apiKey: process.env.OPENAI_API_KEY, |
| 283 | +}) |
| 284 | + |
| 285 | +const app = new Koa() |
| 286 | + |
| 287 | +app.use(async (ctx, next) => { // TODO: use your favorite routing library |
| 288 | + const { message } = await ctx.request.json() // this example uses koa-body-parsers |
| 289 | + |
| 290 | + const stream = await client.chat.completions.create({ |
| 291 | + model: 'gpt-4o-mini', |
| 292 | + messages: [{ role: 'user', content: messages }], |
| 293 | + stream: true, |
| 294 | + }) |
| 295 | + |
| 296 | + ctx.response.type = 'text/event-stream' |
| 297 | + const body = ctx.body = new PassThrough() |
| 298 | + |
| 299 | + // streaming needs to be handled in a separate event loop |
| 300 | + ;(async () => { |
| 301 | + for await (const chunk of stream) { |
| 302 | + const content = chunk.choices[0]?.delta?.content |
| 303 | + if (!content) continue |
| 304 | + |
| 305 | + body.write(`data: ${JSON.stringify({ |
| 306 | + delta: { |
| 307 | + content: chunk.choices[0].delta.content || '' |
| 308 | + } |
| 309 | + })}}\n\n`) |
| 310 | + |
| 311 | + body.end() |
| 312 | + } |
| 313 | + })().catch((err) => app.emit('error', err)) |
| 314 | +}) |
| 315 | +``` |
0 commit comments