美文网首页
express原理

express原理

作者: 成熟稳重的李先生 | 来源:发表于2019-11-06 21:59 被阅读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;
    

    相关文章

      网友评论

          本文标题:express原理

          本文链接:https://www.haomeiwen.com/subject/smupbctx.html