简单封装一下node的http模块

1 篇文章 0 订阅

代码:

const http = require('http');
const qs = require('qs');
const fs = require('fs');
const Url = require('url');
const path = require('path');
const toJSON = (obj) => {
  return JSON.stringify(obj);
}
const equal = (str1, str2) => {
  return (isString(str1) && isString(str2)) ? 
    str1.toLowerCase() === str2.toLowerCase() :
    str1 === str2;
}
const isString = (str) => {
  return typeof str === 'string';
}
const isObject = (o) => {
  return typeof o === 'object';
}
const isFunction = (fn) => {
  return (fn && 
    [
      "[object Function]",
      "[object AsyncFunction]"
    ].indexOf(Object.prototype.toString.call(fn)) > -1);
}
const isRegexp = (reg) => {
  return Object.prototype.toString.call(reg) === "[object RegExp]";
}
const formatReq = (req, obj = false) => {
  try {
    return Url.parse(req.headers.host + req.url, obj);
  } catch(error) {
    return null;
  }
}

const GET = 'GET',
      POST = 'POST',
      TYPE_FILE = 'file';
const check = ( source , target) => {
  let type = Object.prototype.toString.call(target);
  type = type.split(' ')[1].replace(']', '');
  const Build = {
    RegExp: () => {
      return new RegExp(target).test(source);
    },
    String: () => {
      return source === target;
    },
    Function: () => {
      return target(source);
    }
  }
  return Build[type] ? Build[type]() : false;
}      
class Queue {
  constructor() {
    this.data = [];
  }
  set(item) {
    const d = this.find({url: item.url, type: item.type});
    if( d && d.length > 0 ) {
      d[0].cb.concat(item.cb);
    }else {
      this.push(item);
    }
    return this.data;
  }
  get(o) {
    this.data.find((item) => item === o);
  }
  push(item) {
    this.data.push(item);
  }
  findByUrl(url) {
    return this.data.filter((item) => url === item.url);
  }
  findByMethod(method) {
    return this.data.reduce((item, pre) => {
      if(equal(item.method, method)){
        pre.push(item);
      }
      return pre;
    }, []);
  }
  find(findObj) {
    let result = [...(this.data || [])];
    Object.keys(findObj).map((key) => {
      result = result.filter((item) => {
        return (item[key] && check(findObj[key], item[key]))
      });
    });
    return result;
  }
}
class Trunsfer {
  constructor(req, res) {
    this.request = req;
    this.response = res;
  }
  get req() {
    const { request } = this;
    return Object.assign(this.request, {
      get query() {
        return formatReq(request, true).query;
      },
      get body() {
        if( equal(request.method, GET) ) {
          return this.query;
        } else {
          return async() => {
            return new Promise(( resolve ) => {
              let data = [];
              request.on('data', (chunk) => {
                data.push(chunk);
              })
              request.on('end', () => {
                resolve( Buffer.concat(data) );
              });
            });
          }
        } 
      },
      get parse() {
        return Url.parse;
      }
    })
  }
  get res() {
    const { response } = this;
    return Object.assign(response, {
      send(...args) {
        response.end(...args);
      },
      get parse() {
        return Url.parse;
      }
    });
  }
}
class Http {
  constructor() {
    this.Server = http.createServer(this.callback.bind(this));
    this.Queue = new Queue();
  }
  notFond(res) {
    res.writeHead(404,{'Content-Type' : 'text/html;charset=utf-8'});
    res.end('404');
  }
  run(cb, ...args) {
    cb.map((callback) => {
      if (isFunction(callback)) {
        callback(...args);
      }
    })
  }
  async callback(request, response) {
    const { req, res } = new Trunsfer(request, response);
    const reqObj = formatReq(req);
    const app = this.Queue.find({ method: req.method, url: reqObj.pathname});
    if ( app && app.length > 0 ) {
      app.map(async (item) => {
        if ( item.type && item.type === TYPE_FILE ) {
          await this.readFile(path.resolve(item.root || './', '.' + reqObj.pathname)).then((data) => {
            this.run(item.cb, req, res, data);
          })
          .catch((err) => {
            console.log(err);
          });
          return;
        }
        this.run(item.cb, req, res);
      })
    } else {
      this.notFond(res);
    }
  }
  request(options, callback) {
    const op = isString(options) ? {
      url: options
    }: Object.assign({}, options);
    if (isFunction(callback)) {
      op.cb = [callback];
    }
    this.Queue.set(op);
  }
  get(options, callback) {
    const op = isString(options) ? {
      url: options,
      method: GET
    }: Object.assign({ method: GET }, options);
    this.request(op, callback);
  }
  post(options, callback) {
    const op = isString(options) ? {
      url: options,
      method: POST
    }: Object.assign({ method: POST }, options);
    this.request(op, callback);
  }
  readFile(...args) {
    return new Promise((resolve) => {
      const rs = fs.createReadStream(...args);
      let data = '';
      rs.on('data', (chunk) => {
        data += chunk.toString();
      });
      rs.on('error', (err) => {
        console.log(err);
      });
      rs.on('end', () => {
        resolve(data);
      })
    });
  }
  listen(...options) {
    this.Server.listen(...options);
  }
}
module.exports = Http;

使用代码:

const Http = require('./http');
const qs = require('qs');
const app = new Http();
const sleep = delay => new Promise(resolve => setTimeout(() => resolve(), delay));
// get请求
app.get('/api', async (req, res) => {
  res.writeHead(200, {'Content-Type' : 'text/html;charset=utf-8'});
  console.log('get: data:', req.body);
  // await sleep(2000);
  res.send('哈哈GET');
});
//post请求
app.post('/api', async (req, res) => {
  const data = await req.body()
  res.writeHead(200, {'Content-Type' : 'text/html;charset=utf-8'});
  res.send(data);
});
// jsonp请求
app.get('/jsonp', async (req, res) => {
  const query = req.body;
  res.send(query.callback + `(${JSON.stringify({name: 1111})})`)
})
// 通过正则匹配加载
app.get({
  type: 'file',
  root: './',
  url: /(.*)\.(css|html|img|jpg|js)$/g,
}, async (req, res, data) => {
  res.writeHead(200,{'Content-Type' : 'text/html;charset=utf-8'});
  res.send(data);
});
app.listen(4000);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值