Middleware
Composable message processing pipeline. Chain functions that run on inbound messages before your handler logic. Each middleware receives a context and a next function - call next() to continue, skip it to stop the chain.
Setup
// src/lib/server/pipeline.js
import { createMiddleware } from 'svelte-adapter-uws/plugins/middleware';
export const pipeline = createMiddleware(
// logging
async (ctx, next) => {
console.log(`[${ctx.topic}] ${ctx.event}`);
await next();
},
// auth check
async (ctx, next) => {
const userId = ctx.ws.getUserData()?.userId;
if (!userId) return; // stop chain -- unauthenticated
ctx.locals.userId = userId;
await next();
},
// data enrichment
async (ctx, next) => {
ctx.data = { ...ctx.data, processedAt: Date.now() };
await next();
}
); Usage
// src/hooks.ws.js
import { pipeline } from '$lib/server/pipeline';
export async function message(ws, { data, platform }) {
const msg = JSON.parse(Buffer.from(data).toString());
const ctx = await pipeline.run(ws, msg, platform);
if (!ctx) return; // chain was stopped (e.g. auth failed)
// ctx.locals.userId is available here
// ctx.data has the enriched data
} API
| Method | Description |
|---|---|
pipeline.run(ws, message, platform) | Execute the chain. Returns context or null if stopped |
pipeline.use(fn) | Append a middleware at runtime |
The context object passed to each middleware:
| Field | Description |
|---|---|
ctx.ws | The WebSocket connection |
ctx.message | Original parsed message |
ctx.topic | Message topic (mutable) |
ctx.event | Message event (mutable) |
ctx.data | Message data (mutable) |
ctx.platform | Platform reference |
ctx.locals | Scratch space for middleware to share data |
Limitations
- Server-side only. No client component.
- No state. The middleware itself is stateless - it’s a pure pipeline. Use
ctx.localsto pass data between middlewares within a single message. - Double
next()guard. Callingnext()twice in the same middleware is a no-op (the second call does nothing).
Was this page helpful?