首先还是先感谢github,感谢github上提供此段源码的作者。跟昨晚的来比今天的静态文件服务器有点点复杂些,可以学到很多新的东西。
仔细会发现这次的代码多了一个fs.stat函数和ReadStream对象的pipe函数,stat这个函数是用来获取文件信息。第一个参数是传入文件路径,第二个则是回调函数,回调函数的第二个参数stats的属性为文件的基本信息。pipe函数用于将这个可读流和destination目标可写流连接起来,传入这个流中的数据将会写入到destination流中。通过在必要时暂停和恢复流,来源流和目的流得以保持同步。
该静态文件服务器的改进点在于使用了Last-Modified和If-Modified-Since报文头,可以不必要给浏览器返回它已经存在的文件。顺便可以根据浏览器请求资源的压缩方式返回给资源进行gzip或者deflate压缩。
var PORT = 8000; var http = require("http"); var url = require("url"); var fs = require("fs"); var path = require("path"); var mime = require("./mime").types; var config = require("./config"); var zlib = require("zlib"); var server = http.createServer(function(request, response) { response.setHeader("Server", "Node/V5"); var pathname = url.parse(request.url).pathname; console.log("url = " + pathname); if (pathname.slice(-1) === "/") { pathname = pathname + config.Welcome.file; } var realPath = __dirname + "/" + path.join("assets", path.normalize(pathname.replace(/\.\./g, ""))); console.log("realPath = " + realPath); var pathHandle = function (realPath) { fs.stat(realPath, function (err, stats) { if (err) { response.writeHead(404, "Not Found", {'Content-Type': 'text/plain'}); response.write("stats = " + stats); response.write("This request URL " + pathname + " was not found on this server."); response.end(); } else { if (stats.isDirectory()) { realPath = path.join(realPath, "/", config.Welcome.file); pathHandle(realPath); } else { var ext = path.extname(realPath); ext = ext ? ext.slice(1) : 'unknown'; var contentType = mime[ext] || "text/plain"; response.setHeader("Content-Type", contentType); //获得文件的修改时间 var lastModified = stats.mtime.toUTCString(); var ifModifiedSince = "If-Modified-Since".toLowerCase(); //设置Last-Modified //服务器给浏览器返回文件最后一次修改时间Last-Modified response.setHeader("Last-Modified", lastModified); if (ext.match(config.Expires.fileMatch)) { var expires = new Date(); expires.setTime(expires.getTime() + config.Expires.maxAge * 1000); response.setHeader("Expires", expires.toUTCString()); response.setHeader("Cache-Control", "max-age=" + config.Expires.maxAge); } //服务器接收浏览器发送过来的If-Modified-Since报文头 //日期相同表示该资源没有变化则返回304 //告诉浏览器该资源你已经有了,不需要再请求了 if (request.headers[ifModifiedSince] && lastModified == request.headers[ifModifiedSince]) { response.writeHead(304, "Not Modified"); response.end(); } else { var raw = fs.createReadStream(realPath); var acceptEncoding = request.headers['accept-encoding'] || ""; var matched = ext.match(config.Compress.match); if (matched && acceptEncoding.match(/\bgzip\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'gzip'}); raw.pipe(zlib.createGzip()).pipe(response); } else if (matched && acceptEncoding.match(/\bdeflate\b/)) { response.writeHead(200, "Ok", {'Content-Encoding': 'deflate'}); raw.pipe(zlib.createDeflate()).pipe(response); } else { response.writeHead(200, "Ok"); raw.pipe(response); } } } } }); }; pathHandle(realPath); }); server.listen(PORT); console.log("Server runing at port: " + PORT + ".");
Expires字段声明了一个网页或URL地址不再被浏览器缓存的时间,一旦超过了这个时间,浏览器都应该联系原始服务器。这里设置失效时间为1年。
exports.Expires = { fileMatch: /^(gif|png|jpg|js|css)$/ig, maxAge: 60*60*24*365 }; exports.Compress = { match: /css|js|html/ig }; exports.Welcome = { file: "index.html" };
枚举各种资源的类型,可根据扩展名设置Content-Type。
exports.types = { "css": "text/css", "gif": "image/gif", "html": "text/html", "ico": "image/x-icon", "jpeg": "image/jpeg", "jpg": "image/jpeg", "js": "text/javascript", "json": "application/json", "pdf": "application/pdf", "png": "image/png", "svg": "image/svg+xml", "swf": "application/x-shockwave-flash", "tiff": "image/tiff", "txt": "text/plain", "wav": "audio/x-wav", "wma": "audio/x-ms-wma", "wmv": "video/x-ms-wmv", "xml": "text/xml" };

JavaScript字符串替换方法详解及常见问题解答 本文将探讨两种在JavaScript中替换字符串字符的方法:在JavaScript代码内部替换和在网页HTML内部替换。 在JavaScript代码内部替换字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 该方法仅替换第一个匹配项。要替换所有匹配项,需使用正则表达式并添加全局标志g: str = str.replace(/fi

本教程向您展示了如何将自定义的Google搜索API集成到您的博客或网站中,提供了比标准WordPress主题搜索功能更精致的搜索体验。 令人惊讶的是简单!您将能够将搜索限制为Y

利用轻松的网页布局:8个基本插件 jQuery大大简化了网页布局。 本文重点介绍了简化该过程的八个功能强大的JQuery插件,对于手动网站创建特别有用

因此,在这里,您准备好了解所有称为Ajax的东西。但是,到底是什么? AJAX一词是指用于创建动态,交互式Web内容的一系列宽松的技术。 Ajax一词,最初由Jesse J创造

核心要点 JavaScript 中的 this 通常指代“拥有”该方法的对象,但具体取决于函数的调用方式。 没有当前对象时,this 指代全局对象。在 Web 浏览器中,它由 window 表示。 调用函数时,this 保持全局对象;但调用对象构造函数或其任何方法时,this 指代对象的实例。 可以使用 call()、apply() 和 bind() 等方法更改 this 的上下文。这些方法使用给定的 this 值和参数调用函数。 JavaScript 是一门优秀的编程语言。几年前,这句话可

该帖子编写了有用的作弊表,参考指南,快速食谱以及用于Android,BlackBerry和iPhone应用程序开发的代码片段。 没有开发人员应该没有他们! 触摸手势参考指南(PDF) Desig的宝贵资源

jQuery是一个很棒的JavaScript框架。但是,与任何图书馆一样,有时有必要在引擎盖下发现发生了什么。也许是因为您正在追踪一个错误,或者只是对jQuery如何实现特定UI感到好奇


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3 英文版
推荐:为Win版本,支持代码提示!