Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/middleware-deep-dive/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
'use strict'

/**
* Module dependencies.
*/

var express = require('../../'); // Import from the root of the repo
var app = express();

// 1. Global Logging Middleware
// This runs for EVERY request
app.use(function logger(req, res, next) {
console.log('\n--- New Request ---');
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
console.log('1. Global Logger: Start');

// Hook into response finish to log completion
res.on('finish', () => {
console.log('1. Global Logger: Response Sent');
});

next();
});

// 2. Middleware that modifies the request
app.use(function addTimestamp(req, res, next) {
console.log('2. Timestamp Middleware: Adding req.requestTime');
req.requestTime = Date.now();
next();
});

// 3. Route-specific middleware example
function validateId(req, res, next) {
console.log(' -> ValidateID Middleware: Checking ID...');
if (req.params.id === '0') {
console.log(' -> ValidateID Middleware: ID is 0, throwing error');
return next(new Error('ID cannot be 0'));
}
console.log(' -> ValidateID Middleware: ID is valid');
next();
}

// Route with multiple middleware
app.get('/user/:id',
validateId,
function userHandler(req, res, next) {
console.log('3. Route Handler: Executing');
res.send(`User ID: ${req.params.id}, Requested at: ${req.requestTime}`);
console.log('3. Route Handler: Finished (response sent)');
// Note: We don't call next() here because we sent a response.
}
Comment on lines +46 to +51
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are not using next() it can be omitted from the function signature. The only case when Express cares about the number of arguments in function signature is error handlers (must have exactly 4).

);

// 4. Async Middleware (Express 5 feature)
// Express 5 automatically catches errors in async functions
app.get('/async-error', async function asyncThrower(req, res, next) {
console.log('4. Async Handler: Start');
// Simulating an async operation that fails
await new Promise(resolve => setTimeout(resolve, 100));
console.log('4. Async Handler: Throwing error');
throw new Error('Something went wrong in async land!');
});

// 5. Router-level middleware
var apiRouter = express.Router();

apiRouter.use(function apiLogger(req, res, next) {
console.log(' [API Router] Logger: Start');
next();
});

apiRouter.get('/data', function(req, res) {
console.log(' [API Router] Handler');
res.json({ message: 'Hello from API' });
});

app.use('/api', apiRouter);

// 6. 404 Handler (Matched if no other route matches)
app.use(function notFound(req, res, next) {
console.log('5. 404 Handler: No route matched');
res.status(404).send('Sorry, cant find that!');
});

// 7. Error Handling Middleware
// MUST have 4 arguments: (err, req, res, next)
app.use(function errorHandler(err, req, res, next) {
console.error('6. Error Handler: Caught error:', err.message);
res.status(500).send({ error: err.message });
});

/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
console.log('Try these URLs:');
console.log(' GET http://localhost:3000/user/123');
console.log(' GET http://localhost:3000/user/0 (Triggers error)');
console.log(' GET http://localhost:3000/async-error (Triggers async error)');
console.log(' GET http://localhost:3000/api/data (Router middleware)');
console.log(' GET http://localhost:3000/unknown (404)');
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"express": "^5.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should express have itself as a dependency?

"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
Expand Down