Aller au contenu

HTTP Streaming

Ce contenu n’est pas encore disponible dans votre langue.

Lacis provides two streaming methods on the response object:

  • res.stream(body) — pipe a raw ReadableStream or AsyncIterable<Uint8Array> to the client
  • res.ndjson(iter) — serialize an AsyncIterable of objects as newline-delimited JSON

A companion utility, parseNDJSON(stream), converts an incoming ReadableStream into an AsyncIterable of parsed objects — useful for consuming LLM API responses.

The most common use case: forward a streaming response from an external LLM API directly to your client.

import type { Request, Response } from 'lacis'
export async function POST(req: Request, res: Response) {
const body = await req.json()
const upstream = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
})
res.stream(upstream.body!)
}

res.ndjson(iter) serializes each value from an async iterable as a JSON line. Sets Content-Type: application/x-ndjson automatically.

import type { Request, Response } from 'lacis'
export async function GET(req: Request, res: Response) {
async function* generate() {
for (let i = 0; i < 5; i++) {
yield { index: i, value: Math.random() }
}
}
res.ndjson(generate())
}

Use parseNDJSON to parse an incoming NDJSON stream into objects, transform them, then re-stream to the client.

import { parseNDJSON } from 'lacis'
import type { Request, Response } from 'lacis'
export async function POST(req: Request, res: Response) {
const upstream = await fetch('http://localhost:11434/api/chat', {
method: 'POST',
body: await req.body(),
})
async function* tokens() {
for await (const chunk of parseNDJSON(upstream.body!)) {
const c = chunk as any
if (!c.done) yield { content: c.message?.content ?? '' }
}
}
res.ndjson(tokens())
}
Platformres.stream()res.ndjson()
Node.jsstreamingstreaming
Bunstreamingstreaming
Vercelbufferedbuffered
Netlifybufferedbuffered

res.stream() and res.ndjson() are raw HTTP streaming — no protocol, no reconnection logic, no event naming. Use them when the client (or an upstream service) already handles the format.

Use res.initSSE() when you need the full SSE protocol: named events, retry, and browser EventSource compatibility.