preface


Express is currently the most popular Node.js-based Web framework, which provides a number of powerful features:

  • routing
  • The middleware
  • Static file service
  • The template
  • Error handling
  • Params parameter processing
  • Query parsing… Etc.

This article focuses on routing and middleware!

routing


First, we need to know how to use the Express route

  • Called on an app instance
app.get('/'.function (req, res, next) {
    console.log(1);
    next();
}, function (req, res, next) {
    console.log(11);
    next();
})

app.get('/ 2'.function (req, res, next) {
    console.log(2);
    next();
}, function (req, res, next) {
    console.log(3)
    next()
})
- 
Copy the code

As the above code is visible, we find several features:

* There can be more than one routing handler; * Multiple routes can be registered; * Call next to go to the next handler or route;Copy the code

Registered routing

Let’s take a look at how express registers routes:

Source directory:

The app class inherits proto(i.e. Application.js).

var proto = require('./application');
mixin(app, proto, false);
Copy the code

Then you go into the application and see a method like this, and you call it multiple times in the source code;

// The router is used to load the router. Bind the new router instance to the this._router property. app.lazyrouter =function lazyrouter() {
  if(! this._router) { this._router = new Router({caseSensitive: this.enabled('case sensitive routing'),
      strict: this.enabled('strict routing')}); this._router.use(query(this.get('query parser fn'))); this._router.use(middleware.init(this)); }};Copy the code

And then you see this code down here;

// Methods is an NPM package that contains common methods such as get, post, etc. // And the key is to call app.get(); This._router.get () methods.foreach ()function(method){
  app[method] = function(path){
    if (method === 'get' && arguments.length === 1) {
      // app.get(setting)
      return this.set(path);
    }

    this.lazyrouter();

    var route = this._router.route(path);
    route[method].apply(route, slice.call(arguments, 1));
    returnthis; }; }) // as can be seen in the codeCopy the code

The next step is to enter our Router file.

methods.concat('all').forEach(function(method){
  proto[method] = function(path){var route = this.route(path) // Get method route[method].apply(route, slice.call(arguments, 1));returnthis; }; }); * See if this code is familiar, there is a similar generation in the application file; Add get, post, and other attributes to the proto attribute. Proto is an export object that inherits all of its attributes to the Router method. The get method that's called in the application is actually calling get here, so let's see what it does; It calls the this.route method proto.route =function route(path) {
  var route = new Route(path);
  var layer = new Layer(path, {
    sensitive: this.caseSensitive,
    strict: this.strict,
    end: true
  }, route.dispatch.bind(route));

  layer.route = route;

  this.stack.push(layer);
  returnroute; }; Route = route; route = route; Layer = route; route = route; Add a layer to the router and store a route in the layer. And get in the Router is not the last get methodCopy the code

Finally, we enter the route file to uncover the true nature of the route;

methods.forEach(function(method){
  Route.prototype[method] = function(){
    var handles = flatten(slice.call(arguments));

    for (var i = 0; i < handles.length; i++) {
      var handle = handles[i];
      var layer = Layer('/', {}, handle);
      layer.method = method;

      this.methods[method] = true;
      this.stack.push(layer);
    }
    returnthis; }; }); * Same formula (methods), add get, POST and other methods to the prototype of route class * Call get and other methods, and add multiple layers to the stack of route according to the number of handle methods passed, one layer for each methodCopy the code

So what’s the answer going to be?

Route call:

When it comes to routing express, since it is an HTTP framework, you must first find this code;

-- application.js --
app.listen = function listen() {
  var server = http.createServer(this);
  returnserver.listen.apply(server, arguments); }; * Those familiar with Nodejs know that the callback passed in to http.createserver () is the first call to the request. So obviously this is our app, but what's app? The code below tells us that; -- express.js -- var app =function(req, res, next) { app.handle(req, res, next); }; App.handle () -- application.js -- app.handle =function handle(req, res, callback) {
  var router = this._router;
  var done = callback || finalhandler(req, res, {
    env: this.get('env'),
    onerror: logerror.bind(this)
  });
  if(! router) { debug('no routes defined on app');
    done(a);return;
  }
  router.handle(req, res, done); }; * The app.handle() method calls this._router. Handle, and this._router is not forgotten;Copy the code

Please see the following figure for handle processing on router and route:

The middleware


  • Middleware registration and distribution calls are basically the same as routing, but without the link of creating a route, only exist in router.stack.

If have a problem, hope everybody gives correct ~!

reference

  • Express website
  • Express Combat (4) : Middleware
  • Express Combat (5) : routing
  • Progressive Express source code learning
  • Express source code