express原理

2019-11-06  本文已影响0人  成熟稳重的李先生
// express.js
let http = require("http");
let url = require("url");
let fs = require("fs");
let path = require("path");
let methods = require("methods");

function Application() {
  let app = (req, res) => {
    let index = 0;
    let { pathname } = url.parse(req.url, true);
    let requestMethod = req.method.toLowerCase();
    function next(err) {
      if (index === app.routes.length) {
        res.statusCode = 404;
        return res.end(`Cannot ${requestMethod} ${pathname}`);
      }
      let { path, method, handler } = app.routes[index++];
      if (err) {
        if (method === "middleware" && handler.length === 4) {
          return handler(err, req, res, next);
        } else {
          next(err);
        }
      } else {
        if (method === "middleware") {
          //路径相同可以匹配  路径是/可以匹配 路径开头也可以匹配
          if (
            pathname === path ||
            path === "/" ||
            pathname.startsWith(path + "/")
          ) {
            return handler(req, res, next); // 将next的执行权交给用户,用户来决定是否向下执行
          } else {
            next();
          }
        } else {
          if (path.params) {
            let matches = pathname.match(path);
            if (matches) {
              let [, ...list] = matches;
              req.params = path.params.reduce(
                (acc, cur, idx) => ((acc[cur] = list[idx]), acc),
                {}
              );
              return handler(req, res);
            }
          }
          if (
            ((path === pathname || path === "*") && method === requestMethod) ||
            method === "all"
          ) {
            return handler(req, res);
          }
        }
        next();
      }
    }
    next();
  };
  app.routes = [];
  [...methods, "all"].forEach(method => {
    app[method] = (path, handler) => {
      let params = [];
      if (path.includes(":")) {
        path = path.replace(/:([^/]+)/g, (...[, $1]) => {
          params.push($1);
          return "([^/]+)";
        });
        path = new RegExp(path);
        path.params = params;
      }
      let layer = {
        path,
        method,
        handler
      };
      app.routes.push(layer);
    };
  });
  app.use = (path, handler) => {
    if (typeof handler != "function") {
      handler = path;
      path = "/";
    }
    let layer = {
      path,
      method: "middleware",
      handler
    };
    app.routes.push(layer);
  };
  app.listen = function() {
    let server = http.createServer(app);
    server.listen(...arguments);
  };
  // 内置中间件,每次请求时,都会先走这个中间件处理一下
  app.use((req, res, next) => {
    let url = require("url");
    let { query, pathname } = url.parse(req.url, true);
    req.query = query; // 格式化获取path和query
    req.path = pathname;
    res.send = value => {
      //增强了res.end
      if (typeof value === "object") {
        res.setHeader("Content-Type", "application/json;charset=utf-8");
        res.end(JSON.stringify(value));
      } else if (typeof value === "number") {
        res.statusCode = value;
        let status = require("_http_server").STATUS_CODES;
        res.end(status[value]);
      } else if (typeof value === "string" || Buffer.isBuffer(value)) {
        res.setHeader("Content-Type", "text/html;charset=utf-8");
        res.end(value);
      }
    };
    res.sendFile = p => {
      // mime,处理文件类型
      fs.createReadStream(p).pipe(res);
    };
    next();
  });
  return app;
}

//静态服务中间件 中间件的写法:高阶函数(函数返回一个函数)
Application.static = root => {
  return (req, res, next) => {
    let p = req.path;
    let absPath = path.join(root, p);
    fs.stat(absPath, (err, statObj) => {
      if (err) {
        return next();
      }
      if (statObj.isFile()) {
        fs.createReadStream(absPath).pipe(res);
      }
    });
  };
};

module.exports = Application;
上一篇 下一篇

猜你喜欢

热点阅读