node静态服务器tudo
生活随笔
收集整理的這篇文章主要介紹了
node静态服务器tudo
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
實(shí)現(xiàn)以下功能
- 讀取靜態(tài)文件或目錄
- MIME類型支持
- 緩存支持/控制
- 支持gzip壓縮
- 訪問目錄可以自動(dòng)尋找下面的index.html文件
- Range支持,斷點(diǎn)續(xù)傳
- 圖片防盜鏈
- 后臺(tái)運(yùn)行
基本功能讀取靜態(tài)文件
此功能分為兩部分:
* 1、返回文件調(diào)用fs建立可讀流讀取文件返回客戶端fs.createReadStream(filepath).pipe(res);* 2、返回目錄因?yàn)槭且祷禺?dāng)前請(qǐng)求路徑下的所有目錄,并且支持點(diǎn)擊進(jìn)入下一級(jí),所有返回文件為html采用handlebars模板引擎編輯模板// 處理模板函數(shù)let list = function () {let template = fs.readFileSync(listTemplatePath, 'utf8');return handlebars.compile(template);}// template 文件<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>{{title}}</title></head><body><ul>{{#each files}}<li><a href={{url}}>{{name}}</a></li>{{/each}}</ul></body></html>// 讀取當(dāng)前路徑下的所有目錄let { promisify, inspect } = util;// 轉(zhuǎn)變fs.readdir 異步方法返回promiselet readdirPromise = promisify(fs.readdir);// 返回filepath下所有目錄let files = await readdirPromise(filepath)// 處理files為我們想要的數(shù)據(jù)files = files.map(file => ({name: file,url: path.join(pathname, file),}))// 最終返回客戶端的html// listlet html = this.list({title: pathname,files,});MIME類型支持
res.setHeader('Content-Type', mime.getType(filepath));緩存支持/控制
toCache (req, res, filepath, stat) {// 強(qiáng)制緩存res.setHeader('Cache-Control', 'private,max-age=60'); // http 1.1// private 客戶端可以緩存// public 客戶端和代理服務(wù)器都可以緩存// max-age=60 緩存內(nèi)容將在60秒后失效// no-cache 需要使用對(duì)比緩存驗(yàn)證數(shù)據(jù),強(qiáng)制向源服務(wù)器再次驗(yàn)證// no-store 所有內(nèi)容都不會(huì)緩存,強(qiáng)制緩存和對(duì)比緩存都不會(huì)觸發(fā) res.setHeader('Expires', new Date(Date.now() + 60 * 1000).toUTCString()); // http 1.0// 對(duì)比緩存// last-modifylet ifModifiedSince = req.headers['if-modified-since'];let lastModified = stat.ctime.toGMTString();// etaglet ifNoneMatch = req.headers['if-none-match'];let eTag = cypto.createHash('sha1').update(stat.ctime.toGMTString() + stat.size).digest('hex');if (ifModifiedSince || ifNoneMatch) {if (ifNoneMatch === eTag && lastModified === ifModifiedSince) {res.statusCode = 304;res.end('');return false;}if ((ifModifiedSince && lastModified === ifModifiedSince) || (ifNoneMatch && ifNoneMatch === eTag)) {res.statusCode = 304;res.end('');return false;}}res.setHeader('Last-Modified', lastModified);res.setHeader('ETag', eTag);return true;}壓縮支持
async gzip(req, res, gzipInfo) {let encoding = req.headers['accept-encoding'];let gzipReg = /\bgzip\b/;let deflateReg = /\bdeflate\b/;let type, streamInfo; if (gzipReg.test(encoding)) {streamInfo = gzipInfo ? await gzipPromise(gzipInfo) : zlib.createGzip();type = 'gzip';} else if (deflateReg.test(encoding)) {streamInfo = gzipInfo ? await deflatePromise(gzipInfo) : zlib.createDeflate();type = 'deflate';}if (type) {res.setHeader('Content-Encoding', type);}return streamInfo;}訪問目錄可以自動(dòng)尋找下面的index.html文件
let indexFilepath = path.join(filepath, '/', 'index.html'); try {let statIndex = await statPromise(indexFilepath);if (statIndex) {// 返回 inde.html文件return this.sendFile(req, res, indexFilepath, stat);} } catch (e) {}Range支持,斷點(diǎn)續(xù)傳
range (req, res, filepath, stat) {res.setHeader('Accept-Range', 'bytes'); // 通知客戶端支持獲取部分資源let range = req.headers['range']; // Range: bytes=0-xxxlet start = 0, end = stat.size;if (range) {let result = range.match(/bytes=(\d*)-(\d*)/);start = isNaN(result[1]) ? result[1] : start;end = isNaN(result[2]) ? result[2] : end;}return fs.createReadStream(filepath, {start,end,})}圖片防盜鏈
notSteal (req, res) {console.log(path.join(process.cwd(), 'imgs/load.png'))let refer = req.headers['referer'] || req.headers['refer'];//如果說有refer的話,則表示是從HTML頁面中引用過來的if (refer) {let { host } = Url.parse(refer);if (host !== hostDomain) {// 返回默認(rèn)圖return fs.createReadStream(path.join(process.cwd(), 'imgs/load.png'));}} }開啟子進(jìn)程運(yùn)行
let { spawn } = require('child_process'); let fs = require('fs');let serverPath = '../src/child.js'; let child = spawn('node', [serverPath], {detached: true,stdio: ['ignore', process.stdout, 'ignore'] })child.unref();- 功能尚不完善,之后會(huì)慢慢豐富!
- 更多細(xì)節(jié)源碼請(qǐng)查看我的GitHub sevenStatic
參考
- Node.js靜態(tài)文件服務(wù)器實(shí)戰(zhàn)
總結(jié)
以上是生活随笔為你收集整理的node静态服务器tudo的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu安装Todo
- 下一篇: 做最好的自己