Node框架Express源码

本文介绍了一个基于Node.js的轻量级框架实现,涵盖了HTTP请求处理、路由管理、中间件使用及静态资源服务等功能。该框架支持常见的HTTP方法,如GET、POST,并能处理路径参数和错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    let http = require('http');
    let url = require('url');
    let methods = require('methods');
    let fs = require('fs');
    // 主文件
    function application() {
      function app(req, res) {
        let { pathname } = url.parse(req.url, true);
        let requestMethod = req.method.toLowerCase();
        let i = 0
        function next(err) {
          if (i === app.routes.length) return res.end(`Cannot ${requestMethod} ${pathname}`);
          let layer = app.routes[i++];
          let { path, method, callback } = layer; // 取出来的路径 可能是正则类型
          if (err) { // 有没有错误 是不是错误处理中间件
            if (method === 'middleware' && callback.length === 4) { // 是中间件
              callback(err, req, res, next);
            } else { // 如果有错误 把错误继续传递,找错误处理中间件
              next(err);
            }
          } else {
            if (method === 'middleware') {
              // 中间件  /hello/  /hello/123123
              // 是/  或者 路径相等 以中间件路径开头
              if (path === '/' || path === pathname || pathname.startsWith(path + '/')) {
                callback(req, res, next);
              } else {
                next();
              }
            } else {
              if (path instanceof RegExp) { // 路径参数
                if (path.test(pathname)) { // /article/([^\/]) /article/1
                  let [, ...others] = pathname.match(path); // 匹配出来对用的路径参数
                  req.params = path.params.reduce((memo, next, index) => (memo[next] = others[index], memo), {}); // 把两个数组合并成一个对象
                  return callback(req, res);
                } else {
                  next();
                }
              } else {
                if ((path == pathname || path == '*') && (method == requestMethod || method === 'all')) {
                  callback(req, res);
                } else {
                  next();
                }
              }
            }
          }
        }
        next();
      }
      app.routes = []; // 路由的关系存放处
      
      app.listen = function (...args) {
        let server = http.createServer(app);
        server.listen(...args);
      };
      // 中间件
      app.use = function (path, callback) {
        // 中间件第一个路径参数未传默认
        if (typeof callback !== 'function') {
          callback = path; // 没有传递路径 那么路径就是callback
          path = '/' //路径默认为/ 全部匹配
        }
        let layer = {
          path,
          callback,
          method: 'middleware' // 表示这个layer是一个中间件
        }
        app.routes.push(layer);
      };
    
      // 请求get、post...        
      [...methods, 'all'].forEach(method => {
        app[method] = function (path, callback) {
          // 路径参数    
          if (path.includes(':')) { // 是路径参数 /article/([^\/]*)
            let params = []; // id
            path = path.replace(/:([^\/]*)/g, function () {
              params.push(arguments[1]);
              return '([^\/]*)'
            });
            path = new RegExp(path);
            path.params = params; // 把匹配到的数组 存在路径上
          }
          let layer = {
            method,
            path, // path如果是字符串我就认为是普通的路由
            callback
          }
          app.routes.push(layer);
        }
      })
    
      // 添加默认的一些请求和响应属性        
      app.use(function (req, res, next) {
        let { query, pathname } = require('url').parse(req.url, true);
        req.query = query;
        req.path = pathname;
        res.send = function (value) {
          if (Buffer.isBuffer(value) || typeof value === 'string') {
            res.end(value)
          } else if (typeof value === 'object') {
            res.setHeader('Content-Type', 'text/html;charset=utf8');
            res.end(JSON.stringify(value))
          }
        }
        next();
      })
      return app;
    }
    // 静态服务
    application.static = function (dir) {
      let path = require('path');
      return function (req, res, next) {
        let p = req.path;
        let realPath = path.join(dir, p);
        fs.stat(realPath, function (err, statObj) {
          if (err) {
            next();
          } else {
            if (statObj.isDirectory()) {
    
            } else {
              fs.readFile(realPath, 'utf8', function (err, data) {
                if (err) {
                  next();
                }else{
                  res.end(data);
                }
              })
            }
          }
        })
      }
    }
    module.exports = application;
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值