Express


中间件的组成

中间件函数可以执行以下任何任务:

 

  • 执行任何代码
  • 修改 request 或者 response 响应对象
  • 结束请求响应周期
  • 调用下一个中间件

 

中间件分类

 

  • 应用程序级别中间件
  • 路由级别中间件
  • 错误处理中间件
  • 内置中间件
  • 第三方中间件

 

应用程序级别中间件

 

不关心请求路径:

 
var app = express();

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

限定请求路径:

 

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

限定请求方法:

 

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

多个处理函数:

 

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

多个路由处理函数:

 

app.get(
  "/user/:id",
  function(req, res, next) {
    console.log("ID:", req.params.id);
    next();
  },
  function(req, res, next) {
    res.send("User Info");
  }
);

// handler for the /user/:id path, which prints the user ID
app.get("/user/:id", function(req, res, next) {
  res.end(req.params.id);
});

 

最后一个例子:

 

app.get(
  "/user/:id",
  function(req, res, next) {
    // if the user ID is 0, skip to the next route
    if (req.params.id === "0") next("route");
    // otherwise pass the control to the next middleware function in this stack
    else next();
  },
  function(req, res, next) {
    // render a regular page
    res.render("regular");
  }
);

// handler for the /user/:id path, which renders a special page
app.get("/user/:id", function(req, res, next) {
  res.render("special");
});

 

路由级别中间件

 

创建路由实例:

 

var router = express.Router();

 

示例:

 

var app = express();
var router = express.Router();

// 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.originalUrl);
    next();
  },
  function(req, res, next) {
    console.log("Request Type:", req.method);
    next();
  }
);

// a middleware sub-stack that handles GET requests to the /user/:id path
router.get(
  "/user/:id",
  function(req, res, next) {
    // if the user ID is 0, skip to the next router
    if (req.params.id === "0") next("route");
    // otherwise pass control to the next middleware function in this stack
    else next();
  },
  function(req, res, next) {
    // render a regular page
    res.render("regular");
  }
);

// 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);
 

另一个示例:

 

var app = express();
var router = express.Router();

// predicate the router with a check and bail out when needed
router.use(function(req, res, next) {
  if (!req.headers["x-auth"]) return next("router");
  next();
});

router.get("/", function(req, res) {
  res.send("hello, user!");
});

// use the router and 401 anything falling through
app.use("/admin", router, function(req, res) {
  res.sendStatus(401);
});

 

错误处理中间件

 

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

 

内置中间件

 

  • express.static serves static assets such as HTML files, images, and so on.
  • express.json parses incoming requests with JSON payloads. NOTE: Available with Express 4.16.0+
  • express.urlencoded parses incoming requests with URL-encoded payloads. NOTE: Available with Express 4.16.0+

 

官方支持的中间件列表:

 

  • https://github.com/senchalabs/connect#middleware

 

第三方中间件

 

官方中间件资源:http://expressjs.com/en/resources/middleware.html

 

早期的 Express 内置了很多中间件。后来 Express 在 4.x 之后移除了这些内置中间件,官方把这些功能性中间件以包的形式单独提供出来。这样做的目的是为了保持 Express 本身极简灵活的特性,开发人员可以根据自己的需求去灵活的定制。下面是官方提供的一些常用的中间件解决方案。

Middleware module

Description

Replaces built-in function (Express 3)

body-parser

Parse HTTP request body. See also: body

, co-body

, and raw-body

.

express.bodyParser

compression

Compress HTTP responses.

express.compress

connect-rid

Generate unique request ID.

NA

cookie-parser

Parse cookie header and populate req.cookies

. See also cookies

and keygrip

.

express.cookieParser

cookie-session

Establish cookie-based sessions.

express.cookieSession

cors

Enable cross-origin resource sharing (CORS) with various options.

NA

csurf

Protect from CSRF exploits.

express.csrf

errorhandler

Development error-handling/debugging.

express.errorHandler

method-override

Override HTTP methods using header.

express.methodOverride

morgan

HTTP request logger.

express.logger

multer

Handle multi-part form data.

express.bodyParser

response-time

Record HTTP response time.

express.responseTime

serve-favicon

Serve a favicon.

express.favicon

serve-index

Serve directory listing for a given path.

express.directory

serve-static

Serve static files.

express.static

session

Establish server-based sessions (development only).

express.session

timeout

Set a timeout period for HTTP request processing.

express.timeout

vhost

Create virtual domains.

express.vhost

 

中间件应用

 

输出请求日志中间件

 

功能:实现为任何请求打印请求日志的功能。

 

logger.js 定义并导出一个中间件处理函数:

 

module.exports = (req, res, next) => {
  console.log(`${req.method} -- ${req.path}`);
  next();
};

 

app.js 加载使用中间件处理函数:

 

app.use(logger);

 

统一处理静态资源中间件

 

功能:实现 express.static() 静态资源处理功能

 

static.js 定义并导出一个中间件处理函数:

 

const fs = require("fs");
const path = require("path");

module.exports = function static(pathPrefix) {
  return function(req, res, next) {
    const filePath = path.join(pathPrefix, req.path);
    fs.readFile(filePath, (err, data) => {
      if (err) {
        // 继续往后匹配查找能处理该请求的中间件
        // 如果找不到,则 express 会默认发送 can not get xxx
        return next();
      }
      res.end(data);
    });
  };
};

 

app.js 加载并使用 static 中间件处理函数:

 

// 不限定请求路径前缀
app.use(static("./public"));
app.use(static("./node_modules"));

// 限定请求路径前缀
app.use("/public", static("./public"));
app.use("/node_modules", static("./node_modules"));

 

错误处理

 

参考文档:

  • Error handling

 

常用 API

 

参考文档:

  • 4.x API

 

express

 

  • express.json
  • express.static
  • express.Router
  • express.urlencoded()

 

Application

 

  • app.set
  • app.get
  • app.locals

 

Request

 

  • req.app
  • req.query
  • req.body
  • req.cookies
  • req.ip
  • req.hostname
  • Req.method
  • req.params
  • req.path
  • req.get()

 

Response

 

  • res.locals
  • res.append()
  • res.cookie()
  • res.clearCookie()
  • res.download()
  • res.end()
  • res.json()
  • res.jsonp()
  • res.redirect()
  • res.render()
  • res.send()
  • res.sendStatus()
  • res.set()
  • res.status()

 

Router

 

  • router.all()
  • router.METHOD()
  • router.use()