From d1379b1a0b60f47713308e94d1f38e8e64b376d8 Mon Sep 17 00:00:00 2001 From: Manak Raj <7manakraj@gmail.com> Date: Mon, 11 May 2026 15:35:41 +0530 Subject: [PATCH] docs: improve middleware documentation readability Refactored middleware documentation for better readability, consistency, and beginner-friendly explanations. Improved formatting, section structure, and middleware examples. Signed-off-by: Manak Raj <7manakraj@gmail.com> --- en/guide/using-middleware.md | 289 +++++++++++++++++++++-------------- 1 file changed, 172 insertions(+), 117 deletions(-) diff --git a/en/guide/using-middleware.md b/en/guide/using-middleware.md index c0469d03ca..01785530e2 100644 --- a/en/guide/using-middleware.md +++ b/en/guide/using-middleware.md @@ -9,35 +9,47 @@ redirect_from: "/guide/using-middleware.html" # Using middleware -Express is a routing and middleware web framework that has minimal functionality of its own: An Express application is essentially a series of middleware function calls. +Express is a lightweight routing and middleware web framework. An Express application is essentially a series of middleware function calls executed during the request-response cycle. -_Middleware_ functions are functions that have access to the [request object](/{{ page.lang }}/5x/api.html#req) (`req`), the [response object](/{{ page.lang }}/5x/api.html#res) (`res`), and the next middleware function in the application's request-response cycle. The next middleware function is commonly denoted by a variable named `next`. +_Middleware_ functions are functions that have access to: + +- The [request object](/{{ page.lang }}/5x/api.html#req) (`req`) +- The [response object](/{{ page.lang }}/5x/api.html#res) (`res`) +- The next middleware function in the application's request-response cycle, commonly named `next` Middleware functions can perform the following tasks: -* Execute any code. -* Make changes to the request and the response objects. -* End the request-response cycle. -* Call the next middleware function in the stack. +- Execute any code +- Modify the request and response objects +- End the request-response cycle +- Pass control to the next middleware function + +If a middleware function does not end the request-response cycle, it must call `next()`. Otherwise, the request will remain pending. -If the current middleware function does not end the request-response cycle, it must call `next()` to pass control to the next middleware function. Otherwise, the request will be left hanging. +Express applications can use the following types of middleware: -An Express application can use the following types of middleware: +- [Application-level middleware](#middleware.application) +- [Router-level middleware](#middleware.router) +- [Error-handling middleware](#middleware.error-handling) +- [Built-in middleware](#middleware.built-in) +- [Third-party middleware](#middleware.third-party) - - [Application-level middleware](#middleware.application) - - [Router-level middleware](#middleware.router) - - [Error-handling middleware](#middleware.error-handling) - - [Built-in middleware](#middleware.built-in) - - [Third-party middleware](#middleware.third-party) +You can load middleware functions with an optional mount path. Multiple middleware functions can also be grouped together to create a middleware sub-stack at a specific mount point. -You can load application-level and router-level middleware with an optional mount path. -You can also load a series of middleware functions together, which creates a sub-stack of the middleware system at a mount point. +---

Application-level middleware

-Bind application-level middleware to an instance of the [app object](/{{ page.lang }}/5x/api.html#app) by using the `app.use()` and `app.METHOD()` functions, where `METHOD` is the HTTP method of the request that the middleware function handles (such as GET, PUT, or POST) in lowercase. +Application-level middleware is bound to an instance of the [app object](/{{ page.lang }}/5x/api.html#app) using: + +- `app.use()` +- `app.METHOD()` -This example shows a middleware function with no mount path. The function is executed every time the app receives a request. +where `METHOD` is the lowercase HTTP method such as `get`, `post`, `put`, or `delete`. + +## Middleware without a mount path + +The following middleware runs for every incoming request: ```js const express = require('express') @@ -49,8 +61,9 @@ app.use((req, res, next) => { }) ``` -This example shows a middleware function mounted on the `/user/:id` path. The function is executed for any type of -HTTP request on the `/user/:id` path. +## Middleware mounted on a specific path + +The following middleware runs for all request types on `/user/:id`: ```js app.use('/user/:id', (req, res, next) => { @@ -59,160 +72,182 @@ app.use('/user/:id', (req, res, next) => { }) ``` -This example shows a route and its handler function (middleware system). The function handles GET requests to the `/user/:id` path. +## Route handler example + +This route handles GET requests to `/user/:id`: ```js -app.get('/user/:id', (req, res, next) => { +app.get('/user/:id', (req, res) => { res.send('USER') }) ``` -Here is an example of loading a series of middleware functions at a mount point, with a mount path. -It illustrates a middleware sub-stack that prints request info for any type of HTTP request to the `/user/:id` path. +## Multiple middleware functions + +Middleware functions can be chained together to form a middleware sub-stack: ```js -app.use('/user/:id', (req, res, next) => { - console.log('Request URL:', req.originalUrl) - next() -}, (req, res, next) => { - console.log('Request Type:', req.method) - next() -}) +app.use( + '/user/:id', + (req, res, next) => { + console.log('Request URL:', req.originalUrl) + next() + }, + (req, res, next) => { + console.log('Request Type:', req.method) + next() + } +) ``` -Route handlers enable you to define multiple routes for a path. The example below defines two routes for GET requests to the `/user/:id` path. The second route will not cause any problems, but it will never get called because the first route ends the request-response cycle. +## Route middleware sub-stack -This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path. +The following example demonstrates multiple middleware handlers for the same route: ```js -app.get('/user/:id', (req, res, next) => { - console.log('ID:', req.params.id) - next() -}, (req, res, next) => { - res.send('User Info') -}) - -// handler for the /user/:id path, which prints the user ID -app.get('/user/:id', (req, res, next) => { - res.send(req.params.id) -}) +app.get( + '/user/:id', + (req, res, next) => { + console.log('ID:', req.params.id) + next() + }, + (req, res) => { + res.send('User Info') + } +) ``` -To skip the rest of the middleware functions from a router middleware stack, call `next('route')` to pass control to the next route. - -{% capture next-function %} +> The middleware above ends the request-response cycle using `res.send()`. Any matching routes defined after this will not execute unless `next('route')` is used. -`next('route')` will work only in middleware functions that were loaded by using the `app.METHOD()` or `router.METHOD()` functions. +## Skipping to the next route -{% endcapture %} +Call `next('route')` to skip the remaining middleware functions for the current route. -{% include admonitions/note.html content=next-function %} - -This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path. +> `next('route')` works only in middleware functions loaded using `app.METHOD()` or `router.METHOD()`. ```js -app.get('/user/:id', (req, res, next) => { - // if the user ID is 0, skip to the next route - if (req.params.id === '0') next('route') - // otherwise pass the control to the next middleware function in this stack - else next() -}, (req, res, next) => { - // send a regular response - res.send('regular') -}) - -// handler for the /user/:id path, which sends a special response -app.get('/user/:id', (req, res, next) => { +app.get( + '/user/:id', + (req, res, next) => { + if (req.params.id === '0') { + next('route') + } else { + next() + } + }, + (req, res) => { + res.send('regular') + } +) + +app.get('/user/:id', (req, res) => { res.send('special') }) ``` -Middleware can also be declared in an array for reusability. +## Reusable middleware arrays -This example shows an array with a middleware sub-stack that handles GET requests to the `/user/:id` path +Middleware functions can also be grouped into arrays for better reusability: ```js -function logOriginalUrl (req, res, next) { +function logOriginalUrl(req, res, next) { console.log('Request URL:', req.originalUrl) next() } -function logMethod (req, res, next) { +function logMethod(req, res, next) { console.log('Request Type:', req.method) next() } const logStuff = [logOriginalUrl, logMethod] -app.get('/user/:id', logStuff, (req, res, next) => { + +app.get('/user/:id', logStuff, (req, res) => { res.send('User Info') }) ``` +--- +

Router-level middleware

-Router-level middleware works in the same way as application-level middleware, except it is bound to an instance of `express.Router()`. +Router-level middleware works the same way as application-level middleware, except it is bound to an instance of `express.Router()`. ```js const router = express.Router() ``` -Load router-level middleware by using the `router.use()` and `router.METHOD()` functions. -The following example code replicates the middleware system that is shown above for application-level middleware, by using router-level middleware: +Load router-level middleware using: + +- `router.use()` +- `router.METHOD()` + +The following example demonstrates router-level middleware: ```js const express = require('express') const app = express() const router = express.Router() -// a middleware function with no mount path. This code is executed for every request to the router +// Runs for every request handled by this router router.use((req, res, next) => { console.log('Time:', Date.now()) next() }) -// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path -router.use('/user/:id', (req, res, next) => { - console.log('Request URL:', req.originalUrl) - next() -}, (req, res, next) => { - console.log('Request Type:', req.method) - next() -}) - -// a middleware sub-stack that handles GET requests to the /user/:id path -router.get('/user/:id', (req, res, next) => { - // if the user ID is 0, skip to the next router - if (req.params.id === '0') next('route') - // otherwise pass control to the next middleware function in this stack - else next() -}, (req, res, next) => { - // render a regular page - res.render('regular') -}) - -// handler for the /user/:id path, which renders a special page -router.get('/user/:id', (req, res, next) => { +// Middleware sub-stack +router.use( + '/user/:id', + (req, res, next) => { + console.log('Request URL:', req.originalUrl) + next() + }, + (req, res, next) => { + console.log('Request Type:', req.method) + next() + } +) + +// Route-specific middleware +router.get( + '/user/:id', + (req, res, next) => { + if (req.params.id === '0') { + next('route') + } else { + next() + } + }, + (req, res) => { + res.render('regular') + } +) + +// Special route handler +router.get('/user/:id', (req, res) => { console.log(req.params.id) res.render('special') }) -// mount the router on the app +// Mount router app.use('/', router) ``` -To skip the rest of the router's middleware functions, call `next('router')` -to pass control back out of the router instance. +## Skipping out of a router -This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path. +Use `next('router')` to exit the current router instance and pass control back to the main application. ```js const express = require('express') const app = express() const router = express.Router() -// predicate the router with a check and bail out when needed +// Router guard middleware router.use((req, res, next) => { - if (!req.headers['x-auth']) return next('router') + if (!req.headers['x-auth']) { + return next('router') + } + next() }) @@ -220,19 +255,29 @@ router.get('/user/:id', (req, res) => { res.send('hello, user!') }) -// use the router and 401 anything falling through +// Fallback handler app.use('/admin', router, (req, res) => { res.sendStatus(401) }) ``` +--- +

Error-handling middleware

-Error-handling middleware always takes _four_ arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don't need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors. + +Error-handling middleware always requires **four arguments**: + +```js +(err, req, res, next) +``` + +Even if you do not use `next`, you must include it to ensure Express recognizes the function as error-handling middleware. +
-Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`: +Example: ```js app.use((err, req, res, next) => { @@ -241,38 +286,48 @@ app.use((err, req, res, next) => { }) ``` -For details about error-handling middleware, see: [Error handling](/{{ page.lang }}/guide/error-handling.html). +For more information, see: [Error handling](/{{ page.lang }}/guide/error-handling.html) + +---

Built-in middleware

-Starting with version 4.x, Express no longer depends on [Connect](https://github.com/senchalabs/connect). The middleware -functions that were previously included with Express are now in separate modules; see [the list of middleware functions](https://github.com/senchalabs/connect#middleware). +Starting from Express 4.x, Express no longer depends on [Connect](https://github.com/senchalabs/connect). Middleware previously bundled with Express is now maintained in separate modules. -Express has the following built-in middleware functions: +Express includes the following built-in middleware functions: -- [express.static](/en/5x/api.html#express.static) serves static assets such as HTML files, images, and so on. -- [express.json](/en/5x/api.html#express.json) parses incoming requests with JSON payloads. **NOTE: Available with Express 4.16.0+** -- [express.urlencoded](/en/5x/api.html#express.urlencoded) parses incoming requests with URL-encoded payloads. **NOTE: Available with Express 4.16.0+** +- [express.static](/en/5x/api.html#express.static) + Serves static assets such as HTML files, images, CSS files, and JavaScript files. + +- [express.json](/en/5x/api.html#express.json) + Parses incoming requests with JSON payloads. + +- [express.urlencoded](/en/5x/api.html#express.urlencoded) + Parses incoming requests with URL-encoded payloads. + +---

Third-party middleware

-Use third-party middleware to add functionality to Express apps. +Third-party middleware can be used to add additional functionality to Express applications. -Install the Node.js module for the required functionality, then load it in your app at the application level or at the router level. +Install the required package using npm and load it either at the application level or router level. -The following example illustrates installing and loading the cookie-parsing middleware function `cookie-parser`. +The following example demonstrates the `cookie-parser` middleware: ```bash -$ npm install cookie-parser +npm install cookie-parser ``` ```js const express = require('express') -const app = express() const cookieParser = require('cookie-parser') -// load the cookie-parsing middleware +const app = express() + +// Load cookie-parsing middleware app.use(cookieParser()) ``` -For a partial list of third-party middleware functions that are commonly used with Express, see: [Third-party middleware](../resources/middleware.html). +For more commonly used middleware packages, see: +[Third-party middleware](../resources/middleware.html)