Node核心模块Http

226 阅读4分钟

静态服务器

    let http = require('http');
    let url = require('url'); // pathname,query
    let path = require('path');
    let fs = require('fs');
    let util = require('util');
    let stat = util.promisify(fs.stat);
    let mime = require('mime');
    let server = http.createServer(async function (req,res) {
      let { pathname } = url.parse(req.url);
      let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
      try{
        let statObj = await stat(realPath); // 判断文件是否存在
        if (statObj.isFile()){ // 是文件 返回文件
          res.setHeader('Content-Type', mime.getType(realPath)+';charset=utf-8');
          fs.createReadStream(realPath).pipe(res);
        }else{
          let url = path.join(realPath,'index.html'); // 目录找html
          res.setHeader('Content-Type','text/html;charset=utf-8');
          fs.createReadStream(url).pipe(res);
        }
      }catch(e){ // 不存在返回404
        res.statusCode = 404;
        res.end('Not found');
      }
    });
    
    server.listen(3000,function () {
      console.log(`server start 3000`);
    })

多语言(req.headers['accept-language'];)

    let http = require('http');
    let url = require('url'); 
    let path = require('path');
    let fs = require('fs');
    let obj = {
      'zh-CN':{
        data:'你好,世界'
      },
      en:{
        data:'hello,world'
      },
      ja:{
        data:'こんにちは、世界'
      }
    }
    let defaultLanguage = 'en';
    let server = http.createServer(async function (req,res) {
      // 多语言 (语言包)
      // 1) 根据路径不同返回不同的语言
      // 2) 可以前端配置多语言
      // 3) 服务端配置多语言
      // Accept-Language: zh-CN;q=0.3,zh;q=0.9,en;q=1 请求头
      // [zh-CN, zh;q=0.9, en;q=0.8]
      // 
      let lan = req.headers['accept-language'];
      res.setHeader('Content-Type', 'text/plain;charset=utf8');
      if(lan){
        let lans = lan.split(',').map(l=>{ // 按照,分割
          let [name, q = 1] = l.split(';'); // 并且把数据转化成[{name:'zh-cn',q:1},{name:'zh';q:0.9}]格式
          return {
            name,
            q: q===1?1:Number(q.split('=')[1])
          }
        }).sort((a,b)=>b.q - a.q); // 根据权重排序
        for(let i = 0; i<lans.length;i++){ // 找到对应的语言返回
          let lanName = lans[i].name;
          console.log(lanName)
          if(obj[lanName]){
            return res.end(obj[lanName].data);
          }
        }
        res.end(obj[defaultLanguage].data); // 找不到默认语言
      }else{
        res.end(obj[defaultLanguage].data);
      }
      
    });
    
    server.listen(3000,function () {
      console.log(`server start 3000`);
    })

缓存

强制缓存

  • cache-control (设置的时间秒)
  • expires (设置绝对时间)
    // 304 走浏览器的缓存
    // 缓存的类型 有两种 强制缓存 + 对比缓存
    
    let http = require('http');
    let url = require('url'); // pathname,query
    let path = require('path');
    let fs = require('fs');
    let util = require('util');
    let stat = util.promisify(fs.stat);
    let mime = require('mime');
    // 页面 可能内部引用了一个css  我希望把css缓存
    
    http.createServer(async function (req,res) {
      console.log(req.url);
      // 告诉浏览器十秒内别再找我了 (index.html) 不会的
      res.setHeader('Cache-Control','max-age=10'); // http 1.1
      // 废弃了
      res.setHeader('Exipres', new Date(Date.now() + 10 * 1000).toLocaleString()); // 绝对时间
      let { pathname } = url.parse(req.url);
      let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
      try {
        let statObj = await stat(realPath); // 判断文件是否存在
        if (statObj.isFile()) { // 是文件 返回文件
          res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
          fs.createReadStream(realPath).pipe(res);
        } else {
          let url = path.join(realPath, 'index.html'); // 目录找html
          res.setHeader('Content-Type', 'text/html;charset=utf-8');
          fs.createReadStream(url).pipe(res);
        }
      } catch (e) { // 不存在返回404
        res.statusCode = 404;
        res.end('Not found');
      }
    }).listen(4000);

协商缓存

  • Last-modified(res) 和 If-Modified-Since(req)(通过判断文件的修改时间来判断是否缓存)
    http.createServer(async function (req,res) {
      // 告诉浏览器十秒内别再找我了 (index.html) 不会的
      res.setHeader('Cache-Control','no-cache'); // http 1.1
      // 废弃了
      res.setHeader('Exipres', new Date(Date.now() + 10 * 1000).toLocaleString()); // 绝对时间
      
      // 第一次访问的时候 要给浏览器加一个头 last-modified
      // 第二请求的时候 会自动带一个头 if-modified-since 
      // 如果当前带过来的头和文件当前的状态有出入 说明文件被更改了(时间变了但是内容没更改 会出现再次访问文件的问题)
      
     
      let { pathname } = url.parse(req.url);
      let realPath = path.join(__dirname, pathname); // 拼接真实文件的路径
      try {
        let statObj = await stat(realPath); // 判断文件是否存在
        if (statObj.isFile()) { // 是文件 返回文件'
          let prev = req.headers['if-modified-since'];
          let current = statObj.ctime.toGMTString();
          if (prev === current){ // 当前文件没有更改 去找缓存把
            res.statusCode = 304;
            res.end();
          }else{
            res.setHeader('Last-Modified', statObj.ctime.toGMTString());
            res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
            fs.createReadStream(realPath).pipe(res);
          }
        } else {
          let url = path.join(realPath, 'index.html'); // 目录找html
          res.setHeader('Content-Type', 'text/html;charset=utf-8');
          fs.createReadStream(url).pipe(res);
        }
      } catch (e) { // 不存在返回404
        res.statusCode = 404;
        res.end('Not found');
      }
    }).listen(4000);
  • Etag(res) 和 If-none-match(req)(将文件md5加密,判断每次文件内容是否变化来进行缓存)
    try {
        let statObj = await stat(realPath); // 判断文件是否存在
        if (statObj.isFile()) { // 是文件 返回文件'
          let content = await readFile(realPath);
          let sign = crypto.createHash('md5').update(content).digest('base64');
          let ifNoneMatch = req.headers['if-none-match'];
          if(ifNoneMatch === sign){
            res.statusCode = 304;
            res.end();
          }else{
            res.setHeader('Etag', sign);
            res.setHeader('Content-Type', mime.getType(realPath) + ';charset=utf-8');
            res.end(content);
          }
        } else {
          let url = path.join(realPath, 'index.html'); // 目录找html
          res.setHeader('Content-Type', 'text/html;charset=utf-8');
          fs.createReadStream(url).pipe(res);
        }
      } catch (e) { // 不存在返回404
        res.statusCode = 404;
        res.end('Not found');
      }

Cryto 加密

    // crypto 加密  md5( 摘要算法 )

    // MD5的特点 不可逆
    // 不同的内容加密长度是一样的
    // 如果内容不相同 那么摘要的结果肯定也是不相同的
    let crypto = require('crypto'); 
    
    // let r = crypto.createHash('md5').update('123456777777').digest('base64');
    // console.log(r);
    // r = crypto.createHash('md5').update('4QrcOUm6Wau+VuBX8g+IPg==').digest('base64');
    // console.log(r);
    
    // 加盐算法
    
    // 弄一个密码 根据我的密码进行加密 加密cookie
    let fs = require('fs');
    let s = fs.readFileSync('./rsa_private_key.pem','utf8');
    let r = crypto.createHmac('sha1', s).update('123456').digest('base64');
    
    // 非对称 对称
    console.log(r);