In-Depth Guide to Understanding Middleware

Middleware is a crucial concept in web development, acting as the bridge between the client and server. This post explores the role of middleware in handling requests and responses, enhancing functionality, and improving security. We'll delve into various types of middleware, including logging, authentication, error handling, and more, with practical examples and best practices to help you integrate middleware effectively into your web applications.

EXPRESS JSFULL STACK DEVELOPMENT

Abhay Kumar

5/19/20247 min read

Middleware in the context of Express JS (and web frameworks in general) refers to 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.

These functions can perform a variety of tasks before passing control to the next middleware function, making them an essential part of handling HTTP requests in a web server.

Key Characteristics of Middleware

  1. Access to Request and Response Objects

  2. Control Flow

  3. Chaining

Middleware

  • simple Middleware are just functions that receive three arguments:

    • req the request object, more on this later

    • res the response object, more on this later

    • next a function that passes the req/res objects to the next middleware or route.

  • error handling Middleware are just functions that receive four arguments:

    • err the err object, for error handling

    • req the request object, more on this later

    • res the response object, more on this later

    • next a function that passes the req/res objects to the next middleware or route.

Types of Middleware in Express JS.

Types Of Middleware

  1. Application-Level Middleware

  2. Router-Level Middleware

  3. Error-Handling Middleware

  4. Built-in Middleware

  5. Third-Party Middleware

Application-Level Middleware

Application-level middleware is bound to an instance of the express application object using app.use() or app.METHOD() where METHOD is one of the HTTP methods (e.g., GET, POST).

Router-Level Middleware

Router-level middleware works the same way as application-level middleware except it is bound to an instance of express.Router().

Error-Handling Middleware

Error-handling middleware is defined with four arguments: (err, req, res, next). Express identifies it as an error-handling middleware function.

Built-in Middleware

Express comes with several built-in middleware functions that handle common tasks.

Examples:

  • express.static(): Serves static files.

  • express.json(): Parses incoming requests with JSON payloads.

  • express.urlencoded(): Parses incoming requests with URL-encoded payloads.

Third-Party Middleware

Third-party middleware is created by the community and can be added to your Express app to handle various tasks. These are available as npm packages.

Examples:

  • morgan: HTTP request logger middleware.

  • helmet: Helps secure Express apps by setting various HTTP headers.

  • cors: Enables Cross-Origin Resource Sharing.

Few Method Where Middleware is used

Application Level :- use middleware methods

app.use([path,] middlewareFunction [, middlewareFunction...]) :-

Uses the specified middleware function all/specified path.

defaults path :- “/”

Uses the specified middleware functions at the specified path:

  • the middleware function is executed when the base of the requested path matches path.

  • path :- The path for which the middleware function is invoked; can be any of:

    • A string representing a path.

    • A path pattern.

    • A regular expression pattern to match paths.

    • An array of combinations of any of the above.

  • middlewareFunction :- middlewareFunction functions; can be:

    • A middleware function.

    • A series of middleware functions (separated by commas).

    • An array of middleware functions.

    • A combination of all of the above.

Router Level :- use middleware methods

router.use([path,] middlewareFunction [, middlewareFunction...]) :-

Uses the specified middleware function all/specified path.

defaults path :- “/”

Uses the specified middleware functions at the specified path:

  • the middleware function is executed when the base of the requested path matches path.

  • path :- The path for which the middleware function is invoked; can be any of:

    • A string representing a path.

    • A path pattern.

    • A regular expression pattern to match paths.

    • An array of combinations of any of the above.

  • middlewareFunction :- middlewareFunction functions; can be:

    • A middleware function.

    • A series of middleware functions (separated by commas).

    • An array of middleware functions.

    • A combination of all of the above.

Router Level :- routing methods :- wtih use of middleware function method

  • Routing Methods :-

    • checkout , copy , delete , get , head , lock , merge , mkactivity

    • mkcol , move , m-search , notify , options , patch , post

    • purge , put , report , search , subscribe , trace , unlock , unsubscribe

  • router.METHOD(path, [middlewareFunction, ...] middlewareFunction) :-

    • Routes an HTTP request,

      • where METHOD is the HTTP method of the request,

      • such as GET, PUT, POST, and so on, in lowercase.

    • Thus, the actual methods are router.get(), router.post(), router.put(), and so on

  • router.all(path, [middlewareFunction, ...] middlewareFunction) :- the standard router.METHOD() methods, except it matches all HTTP verbs

  • router.get(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP GET requests

    • to the specified path with the specified middleware functions.

  • router.post(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP POST requests

    • to the specified path with the specified middleware functions.

  • router.put(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP PUT requests

    • to the specified path with the specified middleware functions.

  • router.delete(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP DELETE requests

    • to the specified path with the specified middleware functions.

  • router.route(path) :- Returns an instance of a single route, which you can then use to handle HTTP verbs with optional middleware.

    • Use router.route() to avoid duplicate route names (and thus typo errors)

    • router.route(path).method1(mw [, mw ...]).method2(mw [, mw ...]).method3(mw [, mw ...]).....methodN(mw [, mw ...])

    • ex:- router.route(path).get(mw [, mw ...]).post(mw [, mw ...]).put(mw [, mw ...])

Application Level : - routing methods :- wtih use of middleware function method

  • Routing Methods :-

    • checkout , copy , delete , get , head , lock , merge , mkactivity

    • mkcol , move , m-search , notify , options , patch , post

    • purge , put , report , search , subscribe , trace , unlock , unsubscribe

  • app.METHOD(path, middlewareFunction [, middlewareFunction ...]) :-

    • Routes an HTTP request,

      • where METHOD is the HTTP method of the request,

      • such as GET, PUT, POST, and so on, in lowercase.

    • Thus, the actual methods are app.get(), app.post(), app.put(), and so on

  • app.all(path, middlewareFunction [, middlewareFunction ...]) :- the standard app.METHOD() methods, except it matches all HTTP verbs

  • app.get(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP GET requests

    • to the specified path with the specified middleware functions.

  • app.post(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP POST requests

    • to the specified path with the specified middleware functions.

  • app.put(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP PUT requests

    • to the specified path with the specified middleware functions.

  • app.delete(path, middlewareFunction [, middlewareFunction ...]) :- Routes HTTP DELETE requests

    • to the specified path with the specified middleware functions.

  • app.route(path) :- Returns an instance of a single route, which you can then use to handle HTTP verbs with optional middleware.

    • Use app.route() to avoid duplicate route names (and thus typo errors)

    • app.route(path).method1(mw [, mw ...]).method2(mw [, mw ...]).method3(mw [, mw ...]).....methodN(mw [, mw ...])

    • ex:- app.route(path).get(mw [, mw ...]).post(mw [, mw ...]).put(mw [, mw ...])

Few Use & Example Of Middleware

Application Level :- Single middleware :- with Error-handling

router level :- Single middleware :- with Error-handling

middleWare without error handling without next

middleWare without error handling with next

middleWare with error handling without next

middleWare with error handling with next

routerHandler also consider as middleWare.

Application Level :- with routerHandler which is without error handling without next

router level :- with routerHandler which is without error handling without next

Application Level :- with routerHandler which is without error handling with next

router level :- with routerHandler which is without error handling with next

Application Level :- with routerHandler which is with error handling without next

router level :- with routerHandler which is with error handling without next

Application Level :- with routerHandler which is with error handling with next

router level :- with routerHandler which is with error handling with next

Application Level :- :- with get, post , put , delete :- with routerHandler which is with error handling with next

router level :- :- with get, post , put , delete :- with routerHandler which is with error handling with next

Application Level :- :- routerHandler and multiple middleWare :- which is without error handling with next

router level :- :- routerHandler and multiple middleWare :- which is without error handling with next

Application Level :- :- routerHandler and multiple middleWare :- which is with error handling with next

router level :- :- routerHandler and multiple middleWare :- which is with error handling with next

in using of multiple routerHandler / middleWare

:- which don't call next() (ex:- mw00 , mw01 , mw02 , mw03 , mw13 , mw14 , mw15 , mw16)

:- use that middleWare at last

:- because if first middleWare don't call next() then we can't move on second middleWare

:- next() :- it helps to call next routerHandler/middleWare/function

:- any middleWare call next() then we can move on next middleWare

if you want to make middleWare then create middleWare with error handling with next

because it gives you option to call error, request response and next method

if you next method require then call otherwise don't call

Application Level :- with :- routerHandler and multiple middleWare :- which is with error handling with next

last middleWare/routerHandler is with error handling without next

router level :- with :- routerHandler and multiple middleWare :- which is with error handling with next

last middleWare/routerHandler is with error handling without next

Application Level :- with :- routerHandler and multiple middleWare :- which is with error handling with next

last middleWare/routerHandler is without error handling without next

router level :- with :- routerHandler and multiple middleWare :- which is with error handling with next

last middleWare/routerHandler is without error handling without next

Application Level :- using route method

router level :- using route method

Application Level :- Single middleWare :- without next

router level :- Single middleWare :- without next

Application Level :- Single middleWare :- with next

router level :- Single middleWare :- with next

Application Level :- Single middleWare :- A router is valid middleWare

router level :- Single middleWare :- A router is valid middleWare

Application Level :- Single middleWare :- A router is valid middleWare with error-handling.

router level :- Single middleWare :- A router is valid middleWare with error-handling.

Application Level :- Single middleWare :- A router is valid middleWare with next without error-handling.

router level :- Single middleWare :- A router is valid middleWare with next without error-handling.

Application Level :- series of middleWare :- You can specify more than one middleWare function at the same mount path.

router level :- series of middleWare :- You can specify more than one middleWare function at the same mount path.

Application Level :- series of middleWare :- with error handling:- You can specify more than one middleWare function at the same mount path.

router level :- series of middleWare :- with error handling:- You can specify more than one middleWare function at the same mount path.

Application Level :- Series of middleware :- Use an array to group middleware logically.

router level :- Series of middleware :- Use an array to group middleware logically.

Application Level :- Combination of middleware :- You can combine all the above ways of mounting middleware..

router level :- Combination of middleware :- You can combine all the above ways of mounting middleware..