MasterController
Middleware
A composable pipeline that wraps every request.
Middleware are (ctx, next) functions that run in order around your routes — perfect for logging, auth, body limits, and headers. The scaffold auto-loads every file in middleware/.
A middleware file#
middleware/01-logger.js
export default async (ctx, next) => {
const start = Date.now();
await next(); // run the rest of the pipeline
const ms = Date.now() - start;
console.log(`${ctx.type.toUpperCase()} ${ctx.request.url} — ${ms}ms`);
};Files load alphabetically — prefix with numbers (01-, 02-) to control order. Generate one with master generate middleware auth.
Path-scoped middleware#
Export an object with register(master) to scope middleware to a path:
middleware/02-admin.js
export default {
register: (master) => {
master.pipeline.map('/admin/*', (admin) => {
admin.use(async (ctx, next) => {
if (!ctx.state.user?.isAdmin) {
ctx.response.statusCode = 403;
ctx.response.end('Forbidden');
return;
}
await next();
});
});
},
};Registering manually#
You can also register in server.js between setupServer() and start():
javascript
master.pipeline.use(async (ctx, next) => { /* ... */ await next(); }); Ordering matters
Middleware registered before
start() runs before the terminal routing middleware, so it wraps your controllers. The error handler is registered last and catches anything thrown downstream.The context object#
ctx.request/ctx.response— raw Node objects.ctx.type— the HTTP method.ctx.state— a per-request bag shared with controllers (great for the authenticated user).