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

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

利用node.js构建静态服务器,让你理解底层的服务器是怎样实现的,让你对服务器有一个更好的认识。

实现了如下功能:

  • 读取静态文件
  • MIME类型支持
  • 缓存支持/控制
  • 支持gzip压缩
  • 只能访问指定目录, 不能访问指定目录的上级目录,保证安全
  • 访问目录可以自动寻找下面的index.html文件
  • Range支持,断点续传
  • 发布为可执行命令并可以后台运行,可以通过npm install -g安装

读取静态文件

let { promisify, inspect } = require('util');let stat = promisify(fs.stat);let readdir = promisify(fs.readdir);let statObj = await stat(filepath);if (statObj.isDirectory()) {//如果是目录的话,应该显示目录 下面的文件列表    let files = await readdir(filepath);    files = files.map(file => ({        name: file,        url: path.join(pathname, file)    }));    let html = this.list({        title: pathname,        files    });    res.setHeader('Content-Type', 'text/html');    res.end(html);} else {    this.sendFile(req, res, filepath, statObj);}sendFile(req, res, filepath, statObj) {    if (this.handleCache(req, res, filepath, statObj)) return; //如果走缓存,则直接返回    res.setHeader('Content-Type', mime.getType(filepath) + ';charset=utf-8');// .jpg    let encoding = this.getEncoding(req, res);    let rs = this.getStream(req, res, filepath, statObj);        if (encoding) {        rs.pipe(encoding).pipe(res);    } else {        rs.pipe(res);    }}getStream(req, res, filepath, statObj) {    let start = 0;    let end = statObj.size - 1;    let range = req.headers['range'];    return fs.createReadStream(filepath, {        start, end    });}复制代码

MiMe类型检测

这个很简单,对应的代码是:

let mime = require('mime');res.setHeader('Content-Type', mime.getType(filepath) + ';charset=utf-8');// .jpg复制代码

缓存支持/控制, 对应的代码是:

if (this.handleCache(req, res, filepath, statObj)) return; //如果走缓存,则直接返回handleCache(req, res, filepath, statObj) {    let ifModifiedSince = req.headers['if-modified-since'];    let isNoneMatch = req.headers['is-none-match'];    res.setHeader('Cache-Control', 'private,max-age=30');    res.setHeader('Expires', new Date(Date.now() + 30 * 1000).toGMTString());    let etag = statObj.size;    let lastModified = statObj.ctime.toGMTString();    res.setHeader('ETag', etag);    res.setHeader('Last-Modified', lastModified);    if (isNoneMatch && isNoneMatch != etag) {        return fasle;    }    if (ifModifiedSince && ifModifiedSince != lastModified) {        return fasle;    }    if (isNoneMatch || ifModifiedSince) {        res.writeHead(304);        res.end();        return true;    } else {        return false;    }}复制代码

支持gzip压缩

getEncoding(req, res) {    //Accept-Encoding:gzip, deflate    let acceptEncoding = req.headers['accept-encoding'];    if (/\bgzip\b/.test(acceptEncoding)) {        res.setHeader('Content-Encoding', 'gzip');        return zlib.createGzip();    } else if (/\bdeflate\b/.test(acceptEncoding)) {        res.setHeader('Content-Encoding', 'deflate');        return zlib.createDeflate();    } else {        return null;    }}if (encoding) {    rs.pipe(encoding).pipe(res);} else {    rs.pipe(res);}复制代码

只能访问指定目录, 不能访问指定目录的上级目录,保证安全

假如一个同学用浏览器访问http://localhost:8000/../xxx.js 怎么办捏?浏览器会自动干掉那两个作为父路径的点的。浏览器会把这个路径组装成http://localhost:8000/xxx.js

但是curl命令可以: curl -i http://localhost:8000/../xxx.js

那么怎么办呢?

var realPath = path.join("assets", path.normalize(pathname.replace(/\.\./g, "")));复制代码

强制替换即可。

Range支持,断点续传

getStream(req, res, filepath, statObj) {    let start = 0;    let end = statObj.size - 1;    let range = req.headers['range'];    if (range) {        res.setHeader('Accept-Range', 'bytes');        res.statusCode = 206;//返回整个内容的一块        let result = range.match(/bytes=(\d*)-(\d*)/);        if (result) {            start = isNaN(result[1]) ? start : parseInt(result[1]);            end = isNaN(result[2]) ? end : parseInt(result[2]) - 1;        }    }    return fs.createReadStream(filepath, {        start, end    });}复制代码

*** 发布为可执行命令并可以后台运行,可以通过npm install -g安装

在package中添加:

"bin": {    "studytest": "bin/www"  },复制代码

执行 npm link 这个时候其实就可以全局执行了

最后发布

  • npm adduser
  • npm publish

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

你可能感兴趣的文章
一起谈.NET技术,ASP.NET MVC 2中使用jQuery UI控件详解
查看>>
信息架构,互联网营销
查看>>
java实现简单邮件的发送以及常见问题
查看>>
第四次scrum冲刺
查看>>
linux配置sftp简单过程
查看>>
boost bind 表达式中的是值语义还是指针语义?
查看>>
【哲学】近代认识论学派间的一些分歧
查看>>
理解height 百分比 height:100%
查看>>
JBPM (三) 服务和实例介绍
查看>>
java线程之——sleep()与wait()的区别
查看>>
JavaScript 基础数组循环和迭代的几种方法
查看>>
Nuget发布教程
查看>>
让SQL SERVER自动清理掉处于SLEEPING状态超过30分钟的进程(转)
查看>>
【036】◀▶ 自己写的程序源代码
查看>>
performance_schema 变量
查看>>
Pixhawk 添加超声波定高
查看>>
error while loading shared libraries: xxx.so.x"错误的原因和解决办法
查看>>
在微软平台上运行 SAP 应用程序
查看>>
ubuntu下安装lamp环境
查看>>
常见浏览器兼容性问题与解决方案
查看>>