Tutorial : Web Application tutorial

更新时间:
2024-05-15
下载文档

Tutorial : Web Application tutorial

This article introduces the WebApp development of JSRE. First explain the basic mechanism of the WebApp framework, then introduce some applications of built-in middleware. The content is organized as follows:

The corresponding project for the example can be found in the 'example' directory of JSRE.

Route

Routing refers to how an application’s endpoints (URIs) respond to client requests.

You define routing using methods of the app object that correspond to HTTP methods; for example, app.get() to handle GET requests and app.post() to handle POST requests. For a full list, see app.METHOD. You can also use app.all() to handle all HTTP methods and app.use() to specify middleware as the callback function (See Using middleware for details).

These routing methods specify a callback function (sometimes called “handler functions”) called when the application receives a request to the specified route (endpoint) and HTTP method. In other words, the application “listens” for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.

In fact, the routing methods can have more than one callback function as arguments. With multiple callback functions, it is important to provide next as an argument to the callback function and then call next() within the body of the function to hand off control to the next callback.

The following code is an example of a very basic route.

var WebApp = require('webapp');

// Create app.
var app = WebApp.create('app', 0, socket.sockaddr(socket.INADDR_ANY, 8000));

// respond with "hello world" when a GET request is made to the homepage
app.get('/', function (req, res) {
  res.send('hello world');
});

Route Methods

A route method is derived from one of the HTTP methods, and is attached to an instance of the WebApp class.

The following code is an example of routes that are defined for the GET and the POST methods to the root of the app.

// GET method route
app.get('/', function (req, res) {
  res.send('GET request to the homepage');
});

// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});

WebApp supports methods that correspond to all HTTP request methods: get, post, and so on. For a full list, see app.METHOD.

There is a special routing method, app.all(), used to load middleware functions at a path for all HTTP request methods. For example, the following handler is executed for requests to the route “/secret” whether using GET, POST, PUT, DELETE, or any other HTTP request method.

app.all('/secret', function (req, res, next) {
  console.log('Accessing the secret section ...');
  next(); // pass control to the next handler
});

Route Paths

Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expressions.

The characters ?, +, *, and () are subsets of their regular expression counterparts. The hyphen (-) and the dot (.) are interpreted literally by string-based paths.

If you need to use the dollar character ($) in a path string, enclose it escaped within ([ and ]). For example, the path string for requests at “/data/$book”, would be “/data/([\$])book”.

Query strings are not part of the route path.

Here are some examples of route paths based on strings.

This route path will match requests to the root route, /.

app.get('/', function (req, res) {
  res.send('root');
});

This route path will match requests to /about.

app.get('/about', function (req, res) {
  res.send('about');
});

This route path will match requests to /random.text.

app.get('/random.text', function (req, res) {
  res.send('random.text');
});

Here are some examples of route paths based on string patterns.

This route path will match acd and abcd.

app.get('/ab?cd', function (req, res) {
  res.send('ab?cd');
});

This route path will match abcd, abbcd, abbbcd, and so on.

app.get('/ab+cd', function (req, res) {
  res.send('ab+cd');
});

This route path will match abcd, abxcd, abRANDOMcd, ab123cd, and so on.

app.get('/ab*cd', function (req, res) {
  res.send('ab*cd');
});

This route path will match /abe and /abcde.

app.get('/ab(cd)?e', function (req, res) {
  res.send('ab(cd)?e');
});

Examples of route paths based on regular expressions:

This route path will match anything with an “a” in it.

app.get(/a/, function (req, res) {
  res.send('/a/');
});

This route path will match butterfly and dragonfly, but not butterflyman, dragonflyman, and so on.

app.get(/.*fly$/, function (req, res) {
  res.send('/.*fly$/');
});

Route Parameters

Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.

Route path: /users/:userId/books/:bookId
Request URL: http://<192.168.7.32>:8000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }

To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.

app.get('/users/:userId/books/:bookId', function (req, res) {
  res.send(req.params);
});

The name of route parameters must be made up of “word characters” ([A-Za-z0-9_]).

Since the hyphen (-) and the dot (.) are interpreted literally, they can be used along with route parameters for useful purposes.

Route path: /flights/:from-:to
Request URL: http://<192.168.7.32>:8000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
Route path: /plantae/:genus.:species
Request URL: http://<192.168.7.32>:8000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }

To have more control over the exact string that can be matched by a route parameter, you can append a regular expression in parentheses (()):

Route path: /user/:userId(\d+)
Request URL: http://<192.168.7.32>:8000/user/42
req.params: {"userId": "42"}

Because the regular expression is usually part of a literal string, be sure to escape any \ characters with an additional backslash, for example \\d+.

Route Handlers

You can provide multiple callback functions.

Route handlers can be in the form of a function, or an array of functions as shown in the following examples.

A single callback function can handle a route. For example:

app.get('/example/a', function (req, res) {
  res.send('Hello from A!');
});

More than one callback function can handle a route (make sure you specify the next object). For example:

app.get('/example/b', function (req, res, next) {
  console.log('the response will be sent by the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from B!');
});

Response Methods

The methods on the response object (res) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.

MethodDescription
res.end()End the response process.
res.json()Send a JSON response.
res.redirect()Redirect a request.
res.render()Render a view template.
res.send()Send a response of various types.
res.sendFile()Send a file as an octet stream.
res.sendStatus()Set the response status code and send its string representation as the response body.

app.route()

You can create chainable route handlers for a route path by using app.route(). Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos. For more information about routes, see: Router() documentation.

Here is an example of chained route handlers that are defined by using app.route().

app.route('/book')
  .get(function (req, res) {
    res.send('Get a random book');
  })
  .post(function (req, res) {
    res.send('Add a book');
  })
  .put(function (req, res) {
    res.send('Update the book');
  });

Router

Use the Router class to create modular, mountable route handlers. A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”.

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.

Create a router file named birds.js in the app directory, with the following content:

var Router = require('webapp').Router;
var router = Router.create();

// middleware that is specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});

// define the home page route
router.get('/', function (req, res) {
  res.send('Birds home page');
});

// define the about route
router.get('/about', function (req, res) {
  res.send('About birds');
});

module.exports = router;

Then, load the router module in the app:

var birds = require('./birds');

// ...

app.use('/birds', birds);

The app will now be able to handle requests to /birds and /birds/about, as well as call the timeLog middleware function that is specific to the route.

Middleware

WebApp is a routing and middleware web framework that has minimal functionality of its own: An application is essentially a series of middleware function calls.

Middleware functions are functions that have access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.

Middleware functions can perform the following tasks:

  • Execute any code.
  • Make changes to the request and the response objects.
  • End the request-response cycle.
  • Call the next middleware function in the stack.

If the current middleware function does not end the request-response cycle, it must call next() to pass control to the next middleware function. Otherwise, the request will be left hanging.

An application can use the following types of middleware:

  • Application-level middleware
  • Router-level middleware
  • Error-handling middleware
  • Built-in middleware
  • Third-party middleware

You can load application-level and router-level middleware with an optional mount path. You can also load a series of middleware functions together, which creates a sub-stack of the middleware system at a mount point.

Application-Level Middleware

Bind application-level middleware to an instance of the app object by using the app.use() and app.METHOD() functions, where METHODis the HTTP method of the request that the middleware function handles (such as GET, PUT, or POST) in lowercase.

This example shows a middleware function with no mount path. The function is executed every time the app receives a request.

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

This example shows a middleware function mounted on the /user/:id path. The function is executed for any type of HTTP request on the /user/:id path.

app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

This example shows a route and its handler function (middleware system). The function handles GET requests to the /user/:id path.

app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

Router-Level Middleware

Router-level middleware works in the same way as application-level middleware, except it is bound to an instance of Router.

var Router = require('webapp').Router;
var router = Router.create();

Load router-level middleware by using the router.use() and router.METHOD() functions.

The following example code replicates the middleware system that is shown above for application-level middleware, by using router-level middleware:

var Router = require('webapp').Router;
var router = Router.create();

// a middleware function with no mount path. This code is executed for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', function (req, res, next) {
  console.log('Request URL:', req.url);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// handler for the /user/:id path, which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// mount the router on the app
app.use('/', router);

Error-Handling Middleware

Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors.

Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature (err, req, res, next):

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

For details about error-handling middleware, see: Error handling.

Built-In Middleware

Express has the following built-in middleware:

  • cookieParser Parse Cookie header and populate req.cookies with an object keyed by the cookie names.
  • queryParser Parse Query strings to objects req.query and objects to strings.
  • serveStatic serves static assets such as HTML files, images, and so on.
  • bodyParser Parse incoming request bodies in a middleware before your handlers, available under the req.body property.
  • multer A middleware for handling multipart/form-data, which is primarily used for uploading files.
  • session Use session to identify the specific user.

Error Handling

Error Handling refers to how WebApp catches and processes errors that occur both synchronously and asynchronously. WebApp comes with a default error handler so you don’t need to write your own to get started.

Catching Errors

It’s important to ensure that WebApp catches all errors that occur while running route handlers and middleware.

Errors that occur in synchronous code inside route handlers and middleware require no extra work. If synchronous code throws an error, then WebApp will catch and process it. For example:

app.get('/', function (req, res) {
  throw new Error('BROKEN'); // WebApp will catch this on its own.
})

For errors returned from asynchronous functions invoked by route handlers and middleware, you must pass them to the next() function, where WebApp will catch and process them.

If you pass anything to the next() function, WebApp regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.

You must catch errors that occur in asynchronous code invoked by route handlers or middleware and pass them to WebApp for processing. For example:

app.get('/', function (req, res, next) {
  setTimeout(function () {
    try {
      throw new Error('BROKEN');
    } catch (err) {
      next(err);
    }
  }, 100);
});

The above example uses a try...catch block to catch errors in the asynchronous code and pass them to WebApp. If the try...catchblock were omitted, WebApp would not catch the error since it is not part of the synchronous handler code.

Use promises to avoid the overhead of the try..catch block or when using functions that return promises. For example:

app.get('/', function (req, res, next) {
  Promise.resolve().then(function () {
    throw new Error('BROKEN');
  }).catch(next); // Errors will be passed to WebApp.
});

Since promises automatically catch both synchronous errors and rejected promises, you can simply provide next as the final catch handler and WebApp will catch errors, because the catch handler is given the error as the first argument.

Whichever method you use, if you want WebApp error handlers to be called in and the application to survive, you must ensure that WebApp receives the error.

The Default Error Handler

WebApp comes with a built-in error handler that takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.

If you pass an error to next() and you do not handle it in a custom error handler, it will be handled by the built-in error handler; the error message will be written to the client.

If you call next() with an error after you have started writing the response (for example, if you encounter an error while streaming the response to the client) the WebApp default error handler closes the connection and fails the request.

So when you add a custom error handler, you must delegate to the default WebApp error handler, when the headers have already been sent to the client:

function errorHandler(err, req, res, next) {
  var status = 404;
  var reason = 'Not found';
  if (err instanceof Error) {
    status = typeof err.status === 'number' ? err.status : 500;
    reason = err.message;
    console.warn('finalHandle fail:', err.message);
  }

  if (!res.headersSent) {
    res.sendStatus(status, reason);
  } else {
    req.close();
    console.warn('finalHandle close request');
  }
}

Note that the default error handler can get triggered if you call next() with an error in your code more than once, even if custom error handling middleware is in place.

Writing Error Handlers

Define error-handling middleware functions in the same way as other middleware functions, except error-handling functions have four arguments instead of three: (err, req, res, next). For example:

app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err);
  }
  var status = err.status ? err.status : res.status();
  status = status < 400 ? 500 : status;
  res.status(status).json({status: status, msg: err.message});
});

You define error-handling middleware last, after other app.use() and routes calls; for example:

var bodyParser = require('middleware').bodyParser;

app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(function (err, req, res, next) {
  // logic
});

Responses from within a middleware function can be in any format, such as an HTML error page, a simple message, or a JSON string.

For organizational (and higher-level framework) purposes, you can define several error-handling middleware functions, much as you would with regular middleware functions. For example, to define an error-handler for requests made by using XHR and those without:

var bodyParser = require('middleware').bodyParser;

app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

In this example, the generic logErrors might write request and error information to stderr, for example:

function logErrors (err, req, res, next) {
  console.error(err.stack);
  next(err);
}

Also in this example, clientErrorHandler is defined as follows; in this case, the error is explicitly passed along to the next one.

Notice that when not calling “next” in an error-handling function, you are responsible for writing (and ending) the response.

function clientErrorHandler(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: 'Something failed!' });
  } else {
    next(err);
  }
}

Implement the “catch-all” errorHandler function as follows (for example):

function errorHandler (err, req, res, next) {
  res.status(500);
  res.render('error', { error: err });
}

Template Engines

A template engine enables you to use static template files in your application. At runtime, the template engine replaces variables in a template file with actual values, and transforms the template into an HTML file sent to the client. This approach makes it easier to design an HTML page.

The WebApp uses ejs EJSopen in new window as its default template engines.

Using Template Engines

To render template files, set the following in you application before app.start():

  • views, the directory where the template files are located. Eg: app.set('views', './views'). default: 'views' directory in the application root directory.
  • view engine, the template engine to use. Eg. app.set('view engine', '.ejs'). default: ejs template engines.

After the view engine is set, you don’t have to specify the engine or load the template engine module in your app; WebApp loads the module internally.

Create a ejs template file named index.ejs in the views directory, with the following content:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
  </head>
  <body>
    <h1><%= message %></h1>
  </body>
</html>

Then create a route to render the index.ejs file.

app.get('/', function (req, res) {
  res.render('index', { title: 'Hey', message: 'Hello world!' });
});

When you make a request to the home page, the index.ejs file will be rendered as HTML.

Developing Template Engines

Use the app.engine(ext, callback) method to create your own template engine. ext refers to the file extension, and callback is the template engine function, which accepts the following items as parameters: the location of the file, the options object, and the callback function.

The following code is an example of implementing a very simple template engine for rendering .te files.

// Define the template engine
app.engine('.te', function (filePath, options, callback) {
  var content = fs.readString(filePath);
  if (!content) {
    return callback(new Error('Read file error.'));
  }

  var rendered = content.replace('#title#', '<title>' + options.title + '</title>')
                        .replace('#message#', '<h1>' + options.message + '</h1>');
  return callback(null, rendered);
});

app.set('views', './views'); // specify the views directory
app.set('view engine', '.te'); // register the template engine

Your app will now be able to render .te files. Create a file named index.te in the 'views' directory with the following content.

#title#
#message#

Then, create the following route in your app.

app.get('/', function (req, res) {
  res.render('index', { title: 'Hey', message: 'Hello World!' });
});

When you make a request to the home page, 'index.te' will be rendered as HTML.

Using Middleware

Access Query Params

When you use the GET method to send a request, you can include the query params in the URL. WebApp has integrated queryParser middleware. WebApp will automatically parse the query parameter, just accessing the query parameter via the req.query object.

The following example shows how to access query params.

// Handle request.
app.get('/query', function (req, res) {
  var bodyCtx = `<p>id:${req.query.id}</p>
                 <p>id:${req.query.name}</p>`;
  var ctx = `
      <html>
      <head>
        <link rel="icon" href="data:image/ico;base64,aWNv">
      </head>
      <body>
        <H1>req querys</H1>
        ${bodyCtx}
      </body>
      </html>`;

  res.send(ctx);
});

You can send request include the query params :

http://<192.168.7.32>:8000/query?id=123&name=foo

Handle Form

The bodyParser middleware parses the post data and saves the result in req.body. The bodyParser middleware can be used to parse the submitted form data.

The follow example shows how to handle a request's form. The bodyParser middleware can also parse other post data. For more information, please refer to bodyParser.

var bodyParser = require('middleware').bodyParser;

// Form page.
app.get('/index.html', function(req, res) {
  var ctx = `
    <html>
    <head>
      <title>file upload</title>
      <link rel="icon" href="data:image/ico;base64,aWNv">
    </head>
    <body>
      <form action="/urlencoded" method="POST">
        First Name: <input type="text" name="first_name"> <br>
        Last Name: <input type="text" name="last_name"> <br>
        pwd: <input type="password" name="pwd"> <br>
        <input type="radio" name="sex" value="male"> male <br>
        <input type="radio" name="sex" value="female">Female <br>
        <input type="checkbox" name="vehicle" value="Bike">I have a bike<br>
        <input type="submit" value="Submit">
      </form>
      </body>
    </html>`;
  res.send(ctx);
});

// Handle request form.
app.post('/urlencoded', bodyParser.urlencoded(), function(req, res){
  var bodyCtx = '';
  for (var k in req.body) {
    bodyCtx += `<p>${k}: ${req.body[k]}</p>`;
  }

  var ctx = `
    <html>
    <head>
      <link rel="icon" href="data:image/ico;base64,aWNv">
    </head>
    <body>
      <H1>req body</H1>
      ${bodyCtx}
    </body>
    </html>`;

  res.send(ctx);
});

Now, you can load the page to submit form.

http://<192.168.7.32>:8000/index.html

You can also set bodyParser.urlencoded() as Independent routing middleware as follow,. It will parser all requests begin with root path.

app.use(bodyParser.urlencoded());

Serving Static Files

To serve static files such as images, CSS files, and JavaScript files, use the serveStatic built-in middleware.

The serveStatic middleware created:

var serveStatic = require('middleware').serveStatic;
serveStatic(root, options);

The root argument specifies the root directory from which to serve static assets. For more information on the options argument, see serveStatic.

For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public:

app.use(serveStatic('./public'));

Now, you can load the files that are in the public directory.

http://<192.168.7.32>:8000/images/logo.gif
http://<192.168.7.32>:8000/css/style.css
http://<192.168.7.32>:8000/js/main.js
http://<192.168.7.32>:8000/hello.html

WebApp looks up the files relative to the static directory, so the name of the static directory is not part of the URL.

To use multiple static assets directories, call the serveStatic middleware function multiple times:

app.use(serveStatic('./public'));
app.use(serveStatic('./files'));

WebApp looks up the files in the order in which you set the static directories with the serveStatic middleware function.

To create a virtual path prefix (where the path does not actually exist in the file system) for files that are served by the serveStatic function, specify a mount path for the static directory, as shown below:

app.use('/static', serveStatic('./public'));

Now, you can load the files that are in the public directory from the /static path prefix.

http://<192.168.7.32>:8000/static/images/logo.gif
http://<192.168.7.32>:8000/static/css/style.css
http://<192.168.7.32>:8000/static/js/main.js
http://<192.168.7.32>:8000/static/hello.html

Upload Files

To update files to server, use the multer built-in middleware.

The multer middleware created:

var multer  = require('middleware').multer;
var upload = multer({ dest: './uploads', limits: {fileSize: 1 * 1024 * 1024}});

The dest option specifies the root directory to which to save update files. limits option specifies limit size of file. For more information on the options argument, see multer.

For example, use the following code to save a file in a directory named uploads. The uploaded file info can be access from req.file object, such as originalname, filename, path, size.

app.post('/single', upload.single('file'), function (req, res, next) {
  var bodyCtx = '';
  for (var k in req.file) { // req.file is the 'file' file
    bodyCtx += `<p>${k}: ${req.file[k]}</p>`;
  }

  var ctx = `
    <html>
    <head>
      <link rel="icon" href="data:image/ico;base64,aWNv">
    </head>
    <body>
      <H1>File info</H1>
      ${bodyCtx}
    </body>
    </html>`;

  res.send(ctx);
});

The request form as follow, enctype="multipart/form-data" is necessary.

<p>Update a single file(.*)</p>
<form action="/single" method="POST" enctype="multipart/form-data">
  File: <input type="file" name="file"><br />
  <input type="submit">
</form>

If you want to specify the upload file types, set the 'access' attribute.

File: <input type="file" name="file" accept=".jpg, .jpeg, .png, .gif"><br />

To upload multiple files, set multipleattribute. The request page as follow.

<p>Update files(.jpg, .jpeg, .png, .gif)</p>
<form action="/mult" method="POST" enctype="multipart/form-data">
  Files: <input type="file" name="photos" accept=".jpg, .jpeg, .png, .gif" multiple><br />
  <input type="submit">
</form>

The follow code show how to handle multiple files once a time:

app.post('/mult', upload.array('photos', 4), function (req, res) {
  // req.files is array of `photos` files
  var bodyCtx = '';
  for (var i in req.files) {
    var file = req.files[i];
    for (var k in file) {
      bodyCtx += `<p>${k}: ${file[k]}</p>`;
    }
    bodyCtx += `<br/>`;
  }

  var ctx = `
    <html>
    <head>
      <link rel="icon" href="data:image/ico;base64,aWNv">
    </head>
    <body>
      <H1>Files info</H1>
      ${bodyCtx}
    </body>
    </html>`;

  res.send(ctx);
});

In the above example, the middleware limits the maximum of 4 files that can be received.

Using Session

The http protocol is stateless, and sometimes we need to track the state of the application. The browser records session information by saving 'cookies'. 'session' is an enhanced session tracking technology implemented on the server side. and It provides better security.s

The session middleware saves session information on the server and records the session information summary in 'cookie'.

Setting the session middleware:

app.use(
  session({
    secret: "keyboard cat",
    resave: false,
    cookie: {
      maxAge: 24 * 3600 * 1000,
    },
    store: new session.SqliteStore(),
  })
);

The main options are explained below. For more options, please refer to session.

  • secret: This is the secret used to sign the session ID cookie.
  • resave: Forces the session to be saved back to the session store, even if the session was never modified during the request. Otherwise set it to false.
  • cookie.maxAge: Specifies the number (in milliseconds) to use when calculating the Expires Set-Cookie attribute.
  • store: The session store instance. MemoryStore and SqliteStore are available in the middleware of session. SqliteStore storage is recommended in production environments.

The following example shows using session to record the number of times a page is viewed by each customer.

app.use(function (req, res, next) {
  if (!req.session.views) {
    req.session.views = {};
  }

  // get the url pathname
  var pathname = req.url;

  // count the views
  req.session.views[pathname] = (req.session.views[pathname] || 0) + 1;

  next();
});

To read session as follow:

// Show viewed times of a page.
app.get('/foo', function (req, res) {
  var ctx = `
    <html>
    <head>
      <link rel="icon" href="data:image/ico;base64,aWNv">
    </head>
    <body>
      <p>you viewed this page(/foo) ${req.session.views['/foo']} times</p>
    </body>
    </html>`;
  res.send(ctx);
});

Now you can load the page to observe how many times the page has been loaded.

http://<192.168.7.32>:8000/foo
文档内容是否对您有所帮助?
有帮助
没帮助