Home  >  Article  >  Web Front-end  >  A brief discussion on how Node.js middleware works

A brief discussion on how Node.js middleware works

PHPz
PHPzforward
2020-09-25 15:47:332623browse

A brief discussion on how Node.js middleware works

What is Express middleware?

  • Middleware literally means anything you put between one layer of software and another.
  • Express middleware is a function executed during the life cycle of a request to the Express server.
  • Each middleware has access to HTTP requests and responses for all routes it is attached to.
  • In addition, middleware can terminate the HTTP request, or use next to pass it to another middleware function. This "chain" of middleware allows you to partition your code and create reusable middleware.

Requirements for writing Express middleware

You need to install a few things to create, use, and test Express middleware. First you need Node and NPM. To make sure it's installed, run:

npm -v && node -v

You should see the installed versions of Node and NPM. If an error occurs, Node needs to be installed. All examples should be used under Node ver 8 and NPM ver 5.

This article uses Express version 4.x. This is important because there were significant changes from version 3.x to version 4.x.

Express Middleware: Basics

First we use Express’s most basic built-in middleware. Create a new project and npm initialize it...

npm init
npm install express --save

Create server.js and paste the following code:

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

app.get('/', (req, res, next) => {
  res.send('Welcome Home');
});

app.listen(3000);

What problem does middleware solve? Why use it?

Suppose you are running a web application using Node.js and Express on a web server. In this app, you need to log in for some pages.

When the web server receives a request for data, Express will provide you with a request object that contains information about the user and the data they requested. Express also gives you access to response objects, which can be modified before the web server responds to the user. These objects are usually shortened to req, res.

Middleware functions are an ideal place to modify the req and res objects with relevant information. For example after a user logs in, you can get their user details from the database and then store these details in res.user.

What does the middleware function look like?

async function userMiddleware (req, res, next) {
    try {
        const userData = await getUserData(req.params.id);  //see app.get below

        if(userData) {
                req.user = userData;
                next();
        }
    } catch(error)  {
        res.status(500).send(error.message); //replace with proper error handling
    }
}

Do not call this function if an error occurs and you do not want to execute other code. Remember to send a response in this case, otherwise the client will wait for a response until it times out.

var app = express();

//your normal route Handlers
app.get('/user/:id', userMiddleware, userController);

Middleware Chaining

You can chain middleware in a middleware array or by using multiple app.use calls:

app.use(middlewareA);
app.use(middlewareB);
app.get('/', [middlewareC, middlewareD], handler);

Express After receiving the request, each middleware that matches the request will be run in the order of initialization until there is a termination operation.

A brief discussion on how Node.js middleware works

So if an error occurs, all middlewares for handling errors will be called in sequence until one of them no longer calls next() until the function is called.

Types of Express middleware

  • Router-level middleware, for example: router.use
  • Built-in middleware, for example: express.static, express.json, express.urlencoded
  • Error handling middleware, for example: app.use(err, req, res, next)
  • Third-party middleware, for example: bodyparser, cookieparser
  • Router-level middleware
  • express.Router Use the express.Router class to create modular, installable routing processing. A routing instance is a complete middleware and routing system.

    • You can use middleware for logging, authentication, etc. As shown below, to log the user's latest activity and parse the authentication header, use it to determine the currently logged in user and add it to the Request object.
    • This function is executed every time the program receives a request. If there is an error, it simply ends the response without invoking subsequent middleware or route processing.
var router = express.Router()
//Load router-level middleware by using the router.use() and router.METHOD() functions.
//The following example creates a router as a module, loads a middleware function in it,
//   defines some routes, and mounts the router module on a path in the main app.
var express = require(‘express’);
var router = express.Router();

// a middleware function with no mount path. This code is executed for
//   every request to the router
// logging
async function logMiddleware (req, res, next) {
    try {
         console.log(req.user.id, new Date());
     next();
    } catch() {
        res.status(500).send(error.message);
    }
}
// authentication
    async function checkAuthentication(req, res, next) => {
// check header or url parameters or post parameters for token
const token = req.body.token || req.query.token || req.headers['x-access-token']
 || req.headers['authorization'];
      if (token) {
        try {
            // verifies secret
            req.decoded = await jwt.verify(token, config.secret)

            let checkUser = await authenticateTokenHelper.getUserDetail(req);

            // if everything is good, save to request for use in other routes
                if (checkUser) {
                        req.user = req.decoded
                        next()
                } else {
                    return res.status(403).json({ 
                    message: responseMessage.noAuthorized 
                    })
                }
        } catch (err) {
            return res.status(401).json({ message: responseMessage.invalidToken })
        }
  } else {
    // if there is no token
    return res.status(400).json({ message: responseMessage.invalidRequest })
  }
}
router.use(logMiddleware);
    router.get('/user, checkAuthentication, handler);

Built-in middleware

Express has the following built-in middleware functions:

  • express.static Provide static resources, such as HTML files, images, etc.
  • express.json Payload parses incoming requests in JSON.
  • express.urlencoded Parses incoming URL-encoded payload requests.

Error handling middleware

Error handling middleware always takes four parameters (err, req, res, next) . You must identify it as an error-handling middleware function by providing four parameters. Even if you don't need to use the next object, you must specify it. Otherwise the next object will be interpreted as a regular middleware and errors will not be handled. The basic signature looks like this:

app.use(function (err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

Example 1:

app.get('/users', (req, res, next) => {
  next(new Error('I am passing you an error!'));
});
app.use((err, req, res, next) => {
  console.log(err);    
  if(!res.headersSent){
    res.status(500).send(err.message);
  }
});

在这种情况下,管道末端的错误处理中间件将会处理该错误。你可能还会注意到,我检查了 res.headersSent 属性。这只是检查响应是否已经将标头发送到客户端。如果还没有,它将向客户端发送 HTTP 500  状态和错误消息。

例2:

你还可以链接错误处理中间件。通常以不同的方式处理不同类型的错误:

app.get('/users, (req, res, next) => {
  let err = new Error('I couldn\'t find it.');
  err.httpStatusCode = 404;
  next(err);
});

app.get('/user, (req, res, next) => {
  let err = new Error('I\'m sorry, you can\'t do that, Dave.');
  err.httpStatusCode = 304;
  next(err);
});

app.use((err, req, res, next) => {
   // handles not found errors
  if (err.httpStatusCode === 404) {
    res.status(400).render('NotFound');
  }
   // handles unauthorized errors 
  else if(err.httpStatusCode === 304){
    res.status(304).render('Unauthorized');
  }
    // catch all
   else if (!res.headersSent) {
     res.status(err.httpStatusCode || 500).render('UnknownError');
  }
  next(err);
});
  • 在这种情况下,中间件检查是否抛出了 404(not found)错误。如果是,它将渲染 “NotFound” 模板页面,然后将错误传递到中间件中的下一项。
  • 下一个中间件检查是否抛出了 304(unauthorized)错误。如果是,它将渲染“Unauthorized”页面,并将错误传递到管道中的下一个中间件。
  • 最后,“catch all” 错误处理仅记录错误,如果未发送响应,它将发送错误的 httpStatusCode(如果未提供则发送 HTTP 500 状态)并渲染 “UnknownError” 模板。

第三方级别的中间件

在某些情况下,我们将向后端添加一些额外的功能。先安装 Node.js 模块获取所需的功能,然后在应用级别或路由器级别将其加载到你的应用中。

示例:当 body-parser 处理 Content-Type 请求标头时,所有中间件都将使用解析的正文填充 req.body 属性。

const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
app.post('/save',(req,res)=>{
    res.json({
        "status":true,
         "payload":req.body
    })
}
app.listen(3000,(req,res)=>{
    console.log('server running on port')
})

总结

中间件功能是一种非常好的方式,可以对每个请求或针对特定路由的每个请求运行代码,并对请求或响应数据采取措施。中间件是现代 Web 服务器的重要组成部分,并且非常有用。

英文原文地址:https://www.thirdrocktechkno.com/blog/how-Node-JS-middleware-works/

为了保证的可读性,本文采用意译而非直译。

更多编程相关知识,请访问:编程入门!!

The above is the detailed content of A brief discussion on how Node.js middleware works. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete