Getting Started with Node.js Development - Routing and Middleware in Express

We have written a HelloWorld example based on Express, and also used the express generator tool to create a HelloExpress project, but some codes have not been explained well, because they involve concepts such as routing and middleware, and it is not clear in a few words, so I specifically An article on routing and middleware.

routing

Usually the format of the HTTP URL is like this:

http://host[:port][path]

http means protocol.

host represents the host.

port is the port, an optional field, the default is 80 if not provided.

path specifies the URI (Uniform Resource Identifier) ​​of the requested resource. If the path is not given in the URL, it will generally default to "/" (usually supplemented by browsers or other HTTP clients).

The so-called routing is how to handle the path part in the HTTP request. For example " http://xxx.com/users/profile " this URL, routing will decide how to handle the path /users/profile.

Let's review the HelloWorld code of the express version provided in Getting Started with Node.js Development - Express Installation and Use :

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

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(8000, function () {
  console.log('Hello World is listening at port 8000');
});

The app.get() call in the above code actually adds a route to our website, specifying that the path "/" is handled by the function represented by the second parameter of get.

The express object can specify routes for common HTTP methods, using the following methods:

app.METHOD(path, callback [, callback ...])

METHOD can be lowercase for HTTP methods such as GET, POST, such as app.get, app.post. The path part can be either a string literal or a regular expression. The simplest example is to change a parameter '/' of the app.get() call in the preceding code to '*', and the meaning is different. Before the change, only access to the form of " http://localhost:8000 " or " http://localhost:8000/ " will return "Hello World!", and after the change, like " http ://localhost:8000/ " localhost:8000/xxx/yyyy.zz ” This visit also returns “Hello World!”.

When building a web server with express, an important part of the job is deciding how to respond to requests for a certain path, aka routing processing.

The most direct route configuration method is to call app.get() and app.post() to configure one by one, but for websites that need to deal with a large number of routes, this will be fatal. Therefore, in our actual development, we need to combine routing parameters (query string, regular expression, custom parameters, post parameters) to reduce workload and improve maintainability. For more detailed information, refer to http://expressjs.com/guide/routing.html .

middleware

There is a concept of middleware in Express . The so-called middleware is some functions that are executed at this stage after receiving the request and before sending the response.

To insert middleware in the processing chain of a route, you can use the use method of the express object. The prototype of this method is as follows:

app.use([path,] function [, function...])

When app.use does not provide the path parameter, the path defaults to "/". When you install a middleware for a path, the middleware will be applied when the path based on that path is accessed. For example, if you set middleware for "/abcd", the middleware will also be applied when "/abcd/xxx" is accessed.

The prototype of the middleware function is as follows:

function (req, res, next)

The first parameter is the Request object req. The second parameter is the Response object res. The third is the function next used to drive the middleware call chain. If you want the subsequent middleware to continue processing requests, you need to call the next method.

A typical call to apply a middleware function to a path looks like this:

app.use('/abcd', function (req, res, next) {
  console.log(req.baseUrl);
  next();
})

app.static middleware

Express provides a static middleware that can be used to process GET requests for static files in a website, which can be accessed through express.static .

The usage of express.static is as follows:

express.static(root, [options])

The first parameter root is the root directory of the static resource to be processed, which can be an absolute path or a relative path. The second optional parameter is used to specify some options, such as maxAge, lastModified, etc. For more options, see here: http://expressjs.com/guide/using-middleware.html#middleware.built-in .

A typical express.static application is as follows:

var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
  }
}

app.use(express.static('public', options));

The above code uses the public directory in the current path as a static file, and the max-age option of the Cache-Control header is 1 day. There are other properties, please refer to the documentation of express.static to understand.

The app.js file of the HelloExpress project created with express has this line of code:

app.use(express.static(path.join(__dirname, 'public')));

This line of code passes the public directory under the HelloExpress directory as a static file to the static middleware for processing, and the corresponding HTTP URI is "/". path is a Node.js module, and __dirname is a global variable of Node.js, pointing to the directory where the currently running js script is located. path.join() is used to concatenate directories.

With the above code, you can access " http://localhost:3000/stylesheets/style.css " in your browser . Let's make a little change and change the above code to the following:

app.use('/static', express.static(path.join(__dirname, 'public')));

The above code uses static middleware for the /static path to process the public directory. At this time, you will use the browser to visit " http://localhost:3000/stylesheets/ " and you will see a 404 page. Change the address to " http://localhost:3000/static/stylesheets/style.css " and you will see a 404 page. That's it.

Router

Express also provides an object called Router, which behaves much like a middleware. You can pass Router directly to app.use to use Router as a middleware. In addition, you can also use the router to handle routing for GET, POST, etc., and you can also use it to add middleware. In short, you can think of the router as a miniature version of the app.

The following code creates a Router instance:

var router = express.Router([options]);

Then you can use router like app (code from http://expressjs.com/4x/api.html#router ):

// invoked for any requests passed to this router
router.use(function(req, res, next) {
  // .. some logic here .. like any other middleware
  next();
});

// will handle any request that ends in /events
// depends on where the router is "use()'d"
router.get('/events', function(req, res, next) {
  // ..
});

Once the router is defined, it can also be passed to app.use as a middleware:

app.use('/events', router);

The above usage will apply the router to the "/events" path in the URL, and the various routing strategies and middleware you configure on the router object will be applied when appropriate.

routing module

The application created by the express tool has a routes directory, which saves the router module applied to the website, index.js and user.js. These two modules are basically the same, let's study index.js.

Here is the content of index.js:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

index.js creates a Router instance and then calls router.get to apply the routing function for the "/" path. Finally, use module.exports to export the Router object.

The following is the code referenced to index.js in app.js:

var routes = require('./routes/index');
...
app.use('/', routes);

The first place, require('./routes/index') uses it as a module, this line of code imports index.js, and saves the router object exported by index.js in the variable routes for subsequent use. Note that the routes in the above code are the routers in index.js.

The second code uses routes as a middleware and mounts it on the "/" path.

module

I saw the usage of module.exports when analyzing index.js earlier. module.exports is used to export an object in a Node.js module. When the caller loads the module with require, it will get an instance of the exported object.

Our index.js exports the Router object. app.js uses require('./routes/index') to get a Router instance.

There is also an auxiliary usage of module.exports, which is to use exports directly to export.

exports.signup = function(req, res){
  //some code
}

exports.login = function(req, res){
  //some code
}

The above code (assuming it is in the users.js file) uses exports directly to export. When using exports to export, the properties and methods you set to exports are actually those of module.exports. The final export of this module is the module.exports object. You can use the method or property set in the form of "exports.signup", and the caller can use it directly after requiring.

The code using the users module might look like this:

var express = require('express');
var app = express();
...
var users = require('./routes/users');
app.post('/signup', users.signup);
app.post('/login', users.login);
...

HelloExpress looking back

Well, with the content introduced earlier, let's look at the application structure and code generated by express, the problem is not big. Now let's summarize the HelloExpress application.

Directory Structure

Express will create applications according to a specific directory structure.

  • In the bin directory, there is a www file, which is actually a js script file. When you use npm start to start the website, www will be called. You can watch the console output to confirm.
  • The public directory contains some static files. The default generated project only has a style.css file under stylesheets. js files can be placed in the javascripts subdirectory, and pictures can be placed in the images subdirectory.
  • The routing module is placed in the routes directory, which has been analyzed earlier. You can configure the routing of your website here.
  • HTML template files placed in the views directory. Let's talk about it next time.
  • The node_modules directory is generated from package.json, which is generated by express
  • app.js, application entry

app.js

The code of app.js is as follows, let’s review it again:

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});


module.exports = app;

Looking at the above code, there should be no pressure. There is only one place, the two lines of code to configure the template engine, behind which the mysterious story is hidden, we will talk about it next time.

Other articles:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324991862&siteId=291194637