用node http模块搭建服务器一直被用做项目实践及开发,深刻学习后,对node搭建http服务器有了新的了解和认识,写此文总结罗列一下node
GZIP最先由Jean-loup Gailly和Mark Adler建立,用于UNIX系统的文件压缩。咱们在Linux中常常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用很是广泛的一种数据压缩格式,或者说一种文件格式。HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点经常使用GZIP压缩技术来让用户感觉更快的速度。这通常是指WWW服务器中安装的一个功能,当有人来访问这个服务器中的网站时,服务器中的这个功能就将网页内容压缩后传输到来访的电脑浏览器中显示出来.通常对纯文本内容可压缩到原大小的40%.这样传输就快了,效果就是你点击网址后会很快的显示出来.固然这也会增长服务器的负载. 通常服务器中都安装有这个功能模块的.
HTTP 请求头 Accept-Encoding 会将客户端可以理解的内容编码方式——一般是某种压缩算法——进行通知。经过内容协商的方式,服务端会选择一个客户端提议的方式,使用并在响应报文首部 Content-Encoding 中通知客户端该选择。
Accept-Encoding:gzip, deflate, br//当前请求支持格式为gzip,defalte,br算法
Content-Encoding:gzip // 当前内容压缩格式为gzipshell
curl -v -H "Accept-Encoding:deflate" http://localhost:8080/msg.txt
npm
function request(req, res) { let { pathname } = url.parse(req.url);// /msg.txt //D:\vipcode\201801\16.http\msg.txt let filepath = path.join(__dirname, pathname); try { // await is only valid in async function let statObj = await stat(filepath); //能够根据不一样的文件内容类型返回不一样的Content-Type res.setHeader('Content-Type', mime.getType(pathname)); //为了兼容不一样的浏览器,node把全部的请求头全转成了小写 let acceptEncoding = req.headers['accept-encoding']; // 内容协商 if (acceptEncoding) { if (acceptEncoding.match(/\bgzip\b/)) { //服务器告诉 客户端我用什么压缩方法压缩了 res.setHeader('Content-Encoding', 'gzip'); fs.createReadStream(filepath).pipe(zlib.createGzip()).pipe(res); } else if (acceptEncoding.match(/\bdeflate\b/)) { res.setHeader('Content-Encoding', 'deflate'); fs.createReadStream(filepath).pipe(zlib.createDeflate()).pipe(res); } else { fs.createReadStream(filepath).pipe(res); } } else { fs.createReadStream(filepath).pipe(res); } } catch (e) { res.statusCode = 404; res.end(); } }
fs.createReadStream(filepath).pipe(zlib.xxx()).pipe(res);
let { promisify } = require('util'); let stat = promisify(fs.stat);
缓存能够减小对服务器的请求,加快请求效率
fs.stat(filepath, (err, stat) => { if (err) { return sendError(req, res); } else { let ifModifiedSince = req.headers['if-modified-since'];//请求头资源上次修改时间 let LastModified = stat.ctime.toGMTString();//文件上次修改时间 if (ifModifiedSince == LastModified) {// 若是相等则返回304 res.writeHead(304); res.end(''); } else { return send(req, res, filepath, stat); } } });
fs.stat(file, (err, stat) => { if (err) { sendError(err, req, res, file, stat); } else { let ifNoneMatch = req.headers['if-none-match']; let etag = crypto.createHash('sha1').update(stat.ctime.toGMTString() + stat.size).digest('hex'); if (ifNoneMatch) { if (ifNoneMatch == etag) { res.writeHead(304); res.end(); } else { send(req, res, file, etag); } } else { send(req, res, file, etag); } } });
res.setHeader('Expires', expires.toUTCString()); res.setHeader('Cache-Control', 'max-age=60');
$ touch hello.shjson
$ chmod +x hello.shwindows
$ ./hello.sh数组
npm i yargs --save
编辑hello.shpromise
let yargs = require('yargs'); //它能够帮咱们解析命令行参数,把参数数组变成对象的形式 // -n --name let argv = yargs.options('n', { alias: 'name',//别名 demand: true,//必填 default: 'yuanyuan', description: '请输入你的姓名' }) .usage('hellp [opitons]') .help()//指定帮助信息 .example('hello -name yuanyuan', '执行hello命令,而后传入name参数为yuanyuan') .alias('h', 'help') .argv; console.log(argv); console.log('hello ' + argv.name);
{ "name": "hello", "bin": { "hello": "hello" } }
执行 npm link 命令。浏览器
$ npm link
就能够直接执行 hello命令了缓存