Three common ways of routing

  This article will introduce the file path, MVC, RESTful three common routing 

  - following from "layman node.js"

 

  1. Type the file path

  1.1 static file

  Route this way had a brief description of the path to resolve part of its comforting part is that the same path with the website URL path directory, without conversion, very intuitive. This way the routing process is also very simple, the transmission path of the request corresponding to the file to the client. Such as:

// native achieved 
http.createServer ((REQ, RES) => {
   IF (req.url === '/ Home' ) {
     // assumed that the local server html static view file in the root directory file folder 
    fs. readFile ( '/ View /' + + req.url '.html', (ERR, Data) => { 
      res.writeHead ( 200 is, { 'the Type-the Content': 'text / HTML' }); 
      res.end ( Data) 
    }) 
  } 
}). the listen () 

// Express 
app.get ( '/ Home', (REQ, RES) => { 
  fs.readFile ( '/ View /' + + req.url '.html', (ERR, Data) => { 
    res.writeHead ( 200 is, { 'the Type-the Content': 'text / HTML' });
    res.status ( 200).send(data)
  })
})

  1.2. Dynamic File

  Before popular MVC pattern, perform dynamic script is a basic routing based on the file path, its processing principle is the Web server to find the corresponding file based on the URL path, such as /index.asp or /index.php. Web server based on the file name suffix to search for parser scripts, and incoming HTTP request context.

  The following is to configure PHP support in Apache way:  

AddType application/x-httpd-php .php

  Parser execute the script, and outputs the response packet, the purpose of the completion of the service. Most of today's servers can be very intelligently according to the suffix serve both dynamic and static files. This approach is not common in the Node, the main reason is the file suffix are .js, tell the back-end script, or front-end script, it's not a good design. And Node in Web server and application service script is one, do not realize in this way.

 

  2. MVC

  Before MVC popular, mainstream treatments are handled by the file path, even thought it was the norm. Until one day developers find the original URL path requested by the user may be nothing to do with the specific path the script is located.

  The main idea of ​​the MVC model is the separation of duties according to business logic, mainly divided into the following.

  , A collection of behaviors  controller (Controller).

   model (Model), and data related to the operation of the package.

   view (View), rendering the view.

 

 

  This is the most classic hierarchical model, roughly, for its mode of operation described below.

   routing resolution, to find the appropriate controller and behavior based URL.

   behavior call the relevant model for data manipulation.

  After  data manipulation, and view call data for page rendering output to the client.

  2.1 manual mapping

  In addition to manual mapping to be manually configured routing outside the more primitive, the URL of its requirements are very flexible, virtually no restrictions on the format. The following URL format could be free map:

  '/user/setting' , '/setting/user'

  It is assumed that the controller already has a user information setting process, as follows:  

exports.setting = (req, res) => {
 // TODO
}

 

  Add a mapping method (registered route) on the line, in order to facilitate the subsequent drafting, use of this method is called (), as shown below:  

const routes = []

const use = (path, action) => {
 routes.push([path, action]);
}

  We determined in a URL entry program, and then executes a corresponding logic, thereby completing the basic route mapping process as follows:

(req, res) => {
  const pathname = url.parse(req.url).pathname
  for (let i = 0; i < routes.length; i++) {
    let route = routes[i];
    if (pathname === route[0]) {
      let action = route[1]
      action(req, res)
      return
    }
  }
  // 处理404请求
  handle404(req, res)
}

  Manual mapping is very convenient, because of its URL is very flexible, so we can both paths are mapped to the same business logic as follows:  

use('/user/setting', exports.setting);
use('/setting/user', exports.setting);

  // even   

use('/setting/user/jacksontian', exports.setting);

  2.1.1   regular match

  For simple path, the above-described matching method can be hard, but completely follows the path request can not meet the demand of:

  '/profile/jacksontian' ,  '/profile/hoover'

  These requests need to show different users different content, there are only two users, if the presence of thousands of users in the system, we are less likely to maintain all the user's manual routing request, so the regular match came into being, we hope you can match to any user in the following way:  

use('/profile/:username',  (req, res) => {
 // TODO
}); 

  So we improve our matching method, when the registration by use routing path needs to be converted to a regular expression, then it is performed by matching, as follows:

const pathRegexp = (path) => {
 let strict = path. path
= path .concat(strict ? '' : '/?') .replace(/\/\(/g, '(?:/') .replace(/(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function (_, slash, format, key, capture, optional, star) { slash = slash || ''; return '' + (optional ? '' : slash) + '(?:' + (optional ? slash : '') + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')' + (optional || '') + (star ? '(/*)?' : ''); }) .replace(/([\/.])/g, '\\$1') .replace(/\*/g, '(.*)'); return new RegExp('^' + path + '$'); }

  Above regular expression is very complex, in general, it can achieve the following matches:

/profile/:username => /profile/jacksontian, /profile/hoover
/user.:ext => /user.xml, /user.json 

  Now that we improve the registration section:

const use = (path, action) => {
  routes.push([pathRegexp(path), action]);
}

  And matching parts:

(req, res) => {
  const pathname = url.parse(req.url).pathname;
  for (let i = 0; i < routes.length; i++) {
    let route = routes[i];
    // 正则匹配
    if (route[0].exec(pathname)) {
      let action = route[1];
      action(req, res);
      return;
    }
  }
  // 处理404请求
  handle404(req, res);
}

  Now our routing function can be achieved regular matches, no longer need to manually route map for a large number of users.

  2.1.2 parameter parsing

  Despite the completion of the regular match, matching a similar URL can be achieved, however: username in the end what matched, yet to be resolved. To do this we need to be further drawn to match the content out, hoping to call in the business such as:

use('/profile/:username', function (req, res) {
 var username = req.params.username;
 // TODO
});

  The objective here is to set the extracted content at req.params. The key first step is extracted, as follows:

pathRegexp = const function (path) { 
  const Keys = []; 
  path = path 
    .concat (strict : '' '' /?? ) 
    .replace ( / \ / \ (/ G, (: / ''? ) 
    .replace ( /(\/)?(\.)?:(\w+)(?:(\(.*?\)))?(\?)?(\*)?/g, function (_, Slash, the format, Key, Capture, 
      optional, Star) { 
      // save key to match up 
      keys.push (Key); 
      Slash = Slash || '' ;
       return '' 
        + (optional '?' : Slash)
         + ' (:? ' 
        ? + (optional Slash:' ')
        + (format || '') + (capture || (format && '([^/.]+?)' || '([^/]+?)')) + ')'
        + (optional || '')
        + (star ? '(/*)?' : '');
    })
    .replace(/([\/.])/g, '\\$1')
    .replace(/\*/g, '(.*)');
  return {
    keys: keys,
    regexp: new RegExp('^' + path + '$')
  };
}

  The key and we will get the actual URL matches the extracted key to the actual value, and to set the req.params, as follows:

(req, res) => {
  const pathname = url.parse(req.url).pathname;
  for (let i = 0; i < routes.length; i++) {
    let route = routes[i];
    // 正则匹配
    let reg = route[0].regexp;
    let keys = route[0].keys;
    let matched = reg.exec(pathname);
    if (matched) {
      // 抽取具体值
      const params = {};
      for (let i = 0, l = keys.length; i < l; i++) {
        let value = matched[i + 1];
        if (value) {
          params[keys[i]] = value;
        }
      }
      req.params = params;
      let action = route[1];
      action(req, res);
      return;
    }
  }
  // 处理404请求
  handle404(req, res);
}

  So far, apart from the query string (req.query) or to submit data (req.body) to fetch the value, but also can take the value from the map's path.

  2.2. Nature Mapping

  The advantage is that the path mapped by hand can be very flexible, but if the project is large, the number of route map will be a lot. From the front path to a specific controller files, you need to review in order to locate the position of the actual code, for which it was suggested that the best route is not as good as free routing. In fact not without route, but the route by way of a convention naturally achieve the routing, without the need to maintain the route map.

  Path analysis section above are implemented such natural mapping is slightly introduced, simple terms, it follows the path division process:

/controller/action/param1/param2/param3 

  To / user / setting / 12/1987, for example, it will look for files in the user directory controllers according to the agreement, after which require it, calling this setting () method file module, while the remaining values ​​passed as arguments directly to this way.

(REQ, RES) => { 
  the let pathname = url.parse (req.url) .pathname; 
  the let Paths = pathname.split ( '/' ); 
  the let Controller = Paths [. 1] || 'index' ; 
  the let Action = Paths [2] || 'index' ; 
  the let args = paths.slice (. 3 ); 
  the let Module1; 

  the try {
     // caching mechanisms require that only the first is blocked 
    module = require ( './ controllers / ' + Controller); 
  } the catch (EX) { 
    handle500 (REQ, RES); 
    return ; 
  } 
  the let Method = Module1 [Action]
   IF (method) {
    method.apply(null, [req, res].concat(args));
  } else {
    handle500(req, res);
  }
}

  Since this method does not specify the name of natural mapping parameters, it can not be extracted using req.params way, but for more concise parameters directly, as shown below:

= exports.setting (REQ, RES, month, year) => {
   // if the path is / user / setting / 12/1987 , then the month is 12, year of 1987 
  // the TODO 
};

  Indeed manual mappings can be passed as a parameter value, rather than through req.params. But this point of view a matter of opinion, not compared and discussed here.

  This route map natural way CodeIgniter PHP MVC framework in wide range of applications, design is very simple, it is also very easy to achieve in the Node. Compared with the manual mapping, if the URL changes, it also needs to document changes occur, manual mapping only changes to the route map can be.

  3. RESTful

  MVC model popular for many years, until the popular RESTful, we realized URL can also be designed to be standardized, the request method can also be distributed as a logical unit.

REST stands for Representational State Transfer, Chinese meaning into the presentation layer state. REST in line with design specifications, we called RESTful design. Its design philosophy is mainly provided by the content server entity as a resource, and performance on the URL.

  For example, a user's address is as follows:

/users/jacksontian 

 

  This address represents a resource, the operation of this resource is mainly reflected in the HTTP request method, it is not reflected in the URL. In the past we add or delete users to change search for perhaps the following URL of this design:

POST /user/add?username=jacksontian
GET /user/remove?username=jacksontian
POST /user/update?username=jacksontian
GET /user/get?username=jacksontian 

  Operating behavior mainly in behavior, request method is mainly used POST and GET. In RESTful design, as it is this:

POST /user/jacksontian
DELETE /user/jacksontian
PUT /user/jacksontian
GET /user/jacksontian 

  It will DELETE and PUT request method to introduce the design, operation and change of state resources involved resources.

  For this specific manifestations of resources, nor another example past performance on the file extension of the URL. Format and design of past suffix resources have great relevance, such as:

GET /user/jacksontian.json
GET /user/jacksontian.xml 

  In RESTful design specific format is determined by the resource request and the field Accept Support for the server header. If a client accepts the response JSON and XML format, it is the Accept field values ​​such as:

Accept: application/json,application/xml

  To fly the server should take into account the field, then you can respond according to the format of the response. In the response packet, the field Content-Type tells the client what format is as follows:

Content-Type: application/json 

  Specific format, which we call specific performance. REST is designed so that, through the URL design resources, methods of operation defined resource request by Accept the decision manifestation of the resource.

  RESTful MVC design does not conflict with, and better improvement. Compared MVC, RESTful HTTP request method just joined the routing process, and reflected more resources on the URL path.

  3.1 Method Request

  In order to be able to support RESTful Node demand, we have improved our design. If you use a method of treatment for all requests, then in RESTful scenario, we need to distinguish between the request method design. Example is shown below:

const routes = { 'all': [] };
const app = {};
app.use = function (path, action) {
  routes.all.push([pathRegexp(path), action]);
};
['get', 'put', 'delete', 'post'].forEach(function (method) {
  routes[method] = [];
  app[method] = function (path, action) {
    routes[method].push([pathRegexp(path), action]);
  };
}); 

  The above code adds the get (), put (), the delete (), post () 4 Ge method, we hope to complete the route mapped by the following ways:

// add user 
app.post ( '/ the User /: username' , addUser);
 // delete user 
App. The Delete ( '/ the User /: username' , removeUser);
 // modify user 
app.put ( '/ user / : username ' , the updateUser);
 // querying user 
app.get (' / user /: username ', getUser);

  Such a request can identify a routing method, and traffic distribution. In order to make distribution more concise section, part of our first match was drawn match () method, as follows:

const match = (pathname, routes) => {
  for (let i = 0; i < routes.length; i++) {
    let route = routes[i];
    // 正则匹配
    let reg = route[0].regexp;
    let keys = route[0].keys;
    let matched = reg.exec(pathname);
    if (matched) {
      // 抽取具体值
      const params = {};
      for (let i = 0, l = keys.length; i < l; i++) {
        let value = matched[i + 1];
        if (value) {
          params[keys[i]] = value;
        }
      }
      req.params = params;
      let action = route[1];
      action(req, res);
      return true;
    }
  }
  return false;
}; 

  Then improve our distribution section as follows:

(REQ, RES) => { 
  the let pathname = url.parse (req.url) .pathname;
   // the request method lowercase 
  the let Method = req.method.toLowerCase ();
   IF (routes.hasOwnPerperty (Method)) {
     // distribution requesting method 
    IF (match (pathname, routes [method])) {
       return ; 
    } the else {
       // If no paths match is found, try to get all () to process the 
      IF (match (pathname, routes.all) ) {
         return ; 
      } 
    } 
  } the else {
     // directly from all () to process the 
    IF (match (pathname, routes.all)) {
      return ; 
    } 
  } 
  // process 404 requests 
  handle404 (REQ, RES); 
}

  So, we have completed the necessary condition for RESTful support. Here implementation using manual methods to complete the mapping, the mapping can be in fact completed by natural RESTful support, but according Controller / Action agreement must be converted to the Resource / Method conventions, where the lead has been achieved ideas, not detail.

  Currently RESTful applications have been widely up, with the front-end business logic of diversification, client, RESTful model with its lightweight design, favored by the majority of developers. For most applications, only need to build a RESTful service interface, you will be able to adapt to a variety of client applications mobile terminal, PC side.

 

  

 

  

 

  

  

  

  

Guess you like

Origin www.cnblogs.com/Mr-CCQT/p/11642395.html