Explain the path mapping (routing) function and control of NodeJS framework express in detail

  • 2021-08-05 08:46:13
  • OfStack

We know that Express is an excellent server-side development framework based on NodeJS. This CSSer will provide route and route control chapters of express framework, and route realizes the path mapping function of URL requested by clients, which can be translated as routing or URL mapping for the time being. If you still don't quite understand, I believe you will gain something after reading this article.

Routing (URL mapping)

Express uses the HTTP action to provide a meaningful and expressive URL mapping API. For example, we may want the URL of the user account to look like "/user/12". The following example can implement such a route, where the value related to the placeholder identifier (in this case: id) can be obtained by req. params.


app.get('/user/:id', function(req, res){

  res.send('user ' + req.params.id);

}); 

In the above example, when we accessed/user/12, we returned "user 12". CSSer Note: app. get is equivalent to registering a listener in the server to listen for get request events. When the requested URL meets the first parameter, the following callback function is executed, and the process is asynchronous.

A route is a simple string that can be internally compiled into a regular expression. For example, when/user/: id is compiled, the internally compiled regular expression string will look like the following (simplified):


\/user\/([^\/]+)\/?

To achieve the complexity, we can pass in the regular expression direct quantity, because the regular capture group is anonymous, so we can access it through req. params. The first capture group should be req. params [0], the second should be req. params [1], and so on.


app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){

  res.send(req.params);

}); 

Test the route we defined with the curl command of Linux:


$ curl http://cssercom:3000/user

[null,null]

$ curl http://cssercom:3000/users

[null,null]

$ curl http://cssercom:3000/users/1

["1",null]

$ curl http://cssercom:3000/users/1..15

["1","15"] 

The following are some routing examples and the associated paths that match them:


"/user/:id"

/user/12

 

"/users/:id?"

/users/5

/users

 

"/files/*"

/files/jquery.js

/files/javascripts/jquery.js

 

"/file/*.*"

/files/jquery.js

/files/javascripts/jquery.js

 

"/user/:id/:operation?"

/user/1

/user/1/edit

 

"/products.:format"

/products.json

/products.xml

 

"/products.:format?"

/products.json

/products.xml

/products

 

"/user/:id.:format?"

/user/12

/user/12.json 

In addition, we can submit json data through POST, and then use bodyParser middleware to parse json request body and return json data to the client:


var express = require('express')

 , app = express.createServer();

app.use(express.bodyParser());

app.post('/', function(req, res){

 res.send(req.body);

});

app.listen(3000); 

Generally, the placeholders we use (such as/user/: id) have no restrictions, that is, users can pass in id values of various data types. If we want to limit users id to numbers, we can write "/user/: id (\ d +)", which can ensure that only the placeholder data type is numeric will be routed.

Routing control

Multiple routes can be defined in one application, and we can control it to turn to the next route. Express provides the third parameter, that is, next () function. When a pattern is not matched, control is transferred back to Connect (Express is based on the Connect module) and the middleware continues to execute in the order in which they were added in use (). This is also true when multiple defined routes are likely to match one URL, unless a route does not call next () and has output a response to the client, they will also be executed in sequence.


app.get('/users/:id?', function(req, res, next){

  var id = req.params.id;

  if (id) {

    // 1 Re-note: If the response content is output to the client here, then the subsequent URL The mapping will not be called 

  } else {

    next(); //  Turn the control down 1 A coincidence URL Routing of 

  }

});

 

app.get('/users', function(req, res){

  // do something else

}); 

The app. all () method can apply a single 1 call entry to all HTTP actions, which is useful in some cases. Let's use this functionality to load a user from our simulated database and assign it to req. user.


var express = require('express')

 , app = express.createServer(); 

var users = [{ name: 'www.csser.com' }];

app.all('/user/:id/:op?', function(req, res, next){

 req.user = users[req.params.id];

 if (req.user) {

  next();

 } else {

  next(new Error('cannot find user ' + req.params.id));

 }

});

app.get('/user/:id', function(req, res){

 res.send('viewing ' + req.user.name);

});

app.get('/user/:id/edit', function(req, res){

 res.send('editing ' + req.user.name);

}); 

app.put('/user/:id', function(req, res){

 res.send('updating ' + req.user.name);

});

app.get('*', function(req, res){

 res.send('what???', 404);

});
app.listen(3000); 

Routing parameter preprocessing

Through implicit data processing, routing parameter preprocessing can greatly improve the readability of application code and request URL verification. If you frequently get common data from several routes, such as loading user information through/user/: id, we may usually do this:


app.get('/user/:userId', function(req, res, next){

 User.get(req.params.userId, function(err, user){

  if (err) return next(err);

  res.send('user ' + user.name);

 });

}); 

Parameters can be mapped to callback functions after preprocessing, which can provide functions such as validation, forced value change, and even loading data from the database. Next, we will call app. param () and pass in the parameters we want to map to some middleware, so we can see that we received the id parameter containing the placeholder (: userId) value. Here, user data loading and error handling can be carried out as usual, and control can be transferred to the next preprocessing or routing (path control) simply by calling next ().


app.param('userId', function(req, res, next, id){

 User.get(id, function(err, user){

  if (err) return next(err);

  if (!user) return next(new Error('failed to find user'));

  req.user = user;

  next();

 });

}); 

In this way, not only to the above mentioned can greatly improve the readability of the route, but also in the whole application to share the logic of this part of the implementation, to achieve the purpose of reuse.


app.get('/user/:userId', function(req, res){

 res.send('CSSer User is  ' + req.user.name);

}); 

For simple cases such as routing placeholder validation and forced value change, only one parameter is passed in (one parameter is supported), and exceptions thrown during this period are automatically passed to next (err).


app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){

  res.send(req.params);

}); 
0

You can also apply callback functions to multiple placeholders at the same time, such as route/commits/: from-: to,: from and: to are numeric types, and we can define them as arrays:


app.get(/^\/users?(?:\/(\d+)(?:\.\.(\d+))?)?/, function(req, res){

  res.send(req.params);

}); 
1

Conclusion

Through the study of this article, we should feel that NodeJS can not only realize the server logic of our products, but also use Javascript to do server programming, paying attention to the server, that is to say, we can use Javascript to customize the functions that can only be done in apache in the past. Do you still need rewrite for NodeJS? Path mapping is simpler and more powerful. Why use rewrite?


Related articles: