博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Node.js 静态服务器新知
阅读量:6594 次
发布时间:2019-06-24

本文共 4244 字,大约阅读时间需要 14 分钟。

用node http模块搭建服务器一直被用作项目实践及开发,深入学习后,对node搭建http服务器有了新的了解和认识,写此文总结罗列一下

  • 支持gzip压缩
  • 缓存支持/控制
  • yargs与自动化

Gzip

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 // 当前内容压缩格式为gzip

可以用命令行设置请求 Accept-Encoding头

curl -v -H "Accept-Encoding:deflate" http://localhost:8080/msg.txt

http与Gzip

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();    }}

根据拿到的 req.headers['accept-encoding'];类型对请求的静态资源进行相同类型的压缩

fs.createReadStream(filepath).pipe(zlib.xxx()).pipe(res);
tip:可以用util模块中的promisify 将一个异步方法转出一个返回promise的方法 (node v8以上)
let { promisify } = require('util'); let stat = promisify(fs.stat);

cache

缓存可以减少对服务器的请求,加快请求效率
  • lastModify
  • etag
  • expires
lastModify 通过最后修改时间来判断缓存是否可用
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);            }        }    });
ETag是实体标签的缩写,根据实体内容生成的一段hash字符串,可以标识资源的状态。当资源发生改变时,ETag也随之发生变化。 ETag是Web服务端产生的,然后发给浏览器客户端。
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);            }        }    });
设置服务器响应消息头字段Expires
res.setHeader('Expires', expires.toUTCString());res.setHeader('Cache-Control', 'max-age=60');

自动化

mac新建自动化shell脚本区别与windows

$ touch hello.sh

$ chmod +x hello.sh

$ ./hello.sh

安装yargs

yargs 模块能够解决如何处理命令行参数。它也需要安装。
npm i yargs --save

编辑hello.sh

let yargs = require('yargs');//它可以帮我们解析命令行参数,把参数数组变成对象的形式// -n  --namelet 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);

添加package.json,并添加以下内容

{  "name": "hello",  "bin": {    "hello": "hello"  }}

执行 npm link 命令。

$ npm link

就可以直接执行 hello命令了

转载地址:http://pqcio.baihongyu.com/

你可能感兴趣的文章
Git查看、删除、重命名远程分支和tag【转】
查看>>
浅谈IM软件业务知识——非对称加密,RSA算法,数字签名,公钥,私钥
查看>>
Oracle中REGEXP_SUBSTR及其它支持正则表达式的内置函数小结
查看>>
正确计算linux系统内存使用率
查看>>
关于MapReduce单词统计的例子:
查看>>
【php】利用php的构造函数与析构函数编写Mysql数据库查询类 (转)
查看>>
导出DLLRegisterServer接口遇到的问题
查看>>
压缩算法
查看>>
ios和android的发展前景比较
查看>>
[转载]SpringMVC的Model参数绑定方式
查看>>
Linux socket多进程服务器框架三
查看>>
Debug.print的用法
查看>>
常用名词
查看>>
第一百三十四节,JavaScript,封装库--遮罩锁屏
查看>>
【转】cookie如何共享到各个浏览器
查看>>
自制基于HMM的python中文分词器
查看>>
如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接
查看>>
RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2-新增锁定用户与解除锁定用户的功能...
查看>>
vue1.0 的过滤器
查看>>
如何删除anaconda
查看>>