UNPKG

master

Version:

Master is a node web-application framework that includes everything needed to create database-backed web applications according to the Model-View-Controller (MVC) pattern

195 lines (152 loc) 4.69 kB
# Middleware Directory This directory contains custom middleware that is auto-discovered and loaded by MasterController. ## How It Works Files in this directory are automatically loaded when the server starts, in **alphabetical order**. Use number prefixes to control execution order: - `01-logger.js` - Runs first - `02-api-auth.js` - Runs second - `03-admin-auth.js` - Runs third ## Middleware Patterns ### Pattern 1: Simple Function Export Export an async function that receives `(ctx, next)`: ```javascript // middleware/01-logger.js module.exports = async (ctx, next) => { console.log(`${ctx.type.toUpperCase()} ${ctx.request.url}`); await next(); // Continue to next middleware console.log(`${ctx.response.statusCode}`); }; ``` ### Pattern 2: Register Function Export an object with a `register()` method for complex middleware: ```javascript // middleware/02-api-auth.js module.exports = { register: (master) => { // Apply middleware only to specific routes master.pipeline.map('/api/*', (api) => { api.use(async (ctx, next) => { // Your middleware logic here await next(); }); }); } }; ``` ## Context Object Middleware receives a context object with: ```javascript { request: req, // Node.js request object response: res, // Node.js response object requrl: parsedUrl, // Parsed URL with query pathName: 'api/users', // Normalized path (lowercase) type: 'get', // HTTP method (lowercase) params: { // Route parameters + query + form data query: {}, // Query string parameters formData: {}, // POST body data userId: '123' // Route parameters (casing preserved!) }, state: {}, // Custom state to share between middleware master: master, // Framework instance isStatic: false // Is this a static file request? } ``` ## Middleware Methods ### Pass-through Middleware Calls `next()` to continue the pipeline: ```javascript master.pipeline.use(async (ctx, next) => { // Before await next(); // After }); ``` ### Terminal Middleware Does NOT call `next()`, ends the pipeline: ```javascript master.pipeline.run(async (ctx) => { ctx.response.end('Done'); }); ``` ### Conditional Middleware Only runs for matching paths: ```javascript master.pipeline.map('/api/*', (api) => { api.use(async (ctx, next) => { // Only runs for /api/* routes await next(); }); }); ``` ### Short-circuiting Don't call `next()` to stop the pipeline: ```javascript module.exports = async (ctx, next) => { if (!isAuthenticated(ctx)) { ctx.response.statusCode = 401; ctx.response.end('Unauthorized'); return; // Don't call next() } await next(); // Continue }; ``` ## Examples See the `.example` files in this directory for complete examples: - `02-api-auth.js.example` - API token authentication - `03-admin-auth.js.example` - Admin route protection To enable an example, remove the `.example` extension. ## Common Use Cases ### Request Timing ```javascript module.exports = async (ctx, next) => { const start = Date.now(); await next(); const duration = Date.now() - start; console.log(`Request took ${duration}ms`); }; ``` ### CORS Headers ```javascript module.exports = async (ctx, next) => { ctx.response.setHeader('Access-Control-Allow-Origin', '*'); await next(); }; ``` ### Authentication Check ```javascript module.exports = async (ctx, next) => { const session = master.sessions.get('user', ctx.request); if (!session) { ctx.response.statusCode = 302; ctx.response.setHeader('Location', '/login'); ctx.response.end(); return; } ctx.state.user = session; await next(); }; ``` ### Response Compression ```javascript const zlib = require('zlib'); module.exports = async (ctx, next) => { await next(); if (ctx.response.statusCode === 200) { // Compress response (simplified example) const acceptEncoding = ctx.request.headers['accept-encoding'] || ''; if (acceptEncoding.includes('gzip')) { ctx.response.setHeader('Content-Encoding', 'gzip'); } } }; ``` ## Disabled by Default Middleware files with `.example` extension are NOT loaded. To enable: ```bash mv 02-api-auth.js.example 02-api-auth.js ``` ## Documentation For more information, see: - [README.md](../README.md) - Complete API documentation - [MasterController Middleware Guide](https://github.com/alexanderrich/mastercontroller)