🟨 JavaScript Q84 / 121

Explain middleware in Node.js.

AI-Powered Answer ✓ Answered

Middleware functions in Node.js (especially within frameworks like Express.js) are functions that have access to the request object (`req`), the response object (`res`), and the `next` middleware function in the application's request-response cycle. They perform tasks, modify the request/response, or terminate the cycle, passing control to the next function if not.

What is Middleware?

In the context of Node.js web frameworks like Express.js, middleware functions are essentially hooks into the request-response lifecycle. Each middleware function receives the request, response, and a function called next. The next function is crucial as it signifies passing control to the subsequent middleware function in the stack. If next() is not called, the request cycle is terminated, and the client will not receive a response unless the current middleware sends one.

Key Characteristics

  • Access to req (request object), res (response object), and next() function.
  • Can execute any code.
  • Can make changes to the request and the response objects.
  • Can end the request-response cycle.
  • Can call the next middleware in the stack.
  • Can short-circuit the request by not calling next() or by sending a response.

Common Use Cases

  • Logging: Recording details about incoming requests.
  • Authentication/Authorization: Verifying user credentials or permissions.
  • Body Parsing: Parsing request bodies (e.g., JSON, URL-encoded data).
  • Error Handling: Centralized handling of errors.
  • Static File Serving: Serving static assets like CSS, JavaScript, images.
  • Routing: Directing requests to specific handlers based on URL and HTTP method.
  • Data Validation: Checking input data format and content.

Example: A Simple Logging Middleware

Here's an example of a simple middleware function that logs the request method and URL to the console.

javascript
const express = require('express');
const app = express();

// Custom logging middleware
const loggerMiddleware = (req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
  next(); // Pass control to the next middleware or route handler
};

// Apply the middleware globally
app.use(loggerMiddleware);

app.get('/', (req, res) => {
  res.send('Hello from Express!');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

How to Use Middleware in Express.js

  • app.use(middlewareFunction): To apply middleware globally to all routes or for a specific path prefix.
  • app.METHOD(path, middlewareFunction, handler): To apply middleware to specific routes and HTTP methods (e.g., app.get, app.post).
  • As an array of functions for a route: app.get('/admin', [authMiddleware, permissionMiddleware], adminHandler);

Order Matters

The order in which middleware functions are defined and applied is critical. They are executed sequentially. For instance, an authentication middleware should run before any route handler that requires a logged-in user. If a body-parser middleware is needed, it must be applied before any route handler attempts to access req.body.

Error Handling Middleware

Express.js handles errors using special middleware functions that take four arguments: (err, req, res, next). These functions are designed to catch and process errors that occur during the request-response cycle. They should be defined last, after all other middleware and routes.

javascript
const express = require('express');
const app = express();

// Simulate a route that throws an error
app.get('/error', (req, res, next) => {
  const error = new Error('Something went wrong!');
  error.status = 400;
  next(error); // Pass the error to the next middleware
});

// Error handling middleware (must be defined last)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(err.status || 500).json({
    message: err.message || 'Internal Server Error',
    status: err.status || 500
  });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});