博文共赏:Node.js静态文件服务器实战

【编者按】《博文共赏》是InfoQ中文站新推出的一个专栏,精选来自国内外技术社区和个人博客上的技术文章,让更多的读者朋友受益,本栏目转载的内容都经过原作者授权。文章推荐可以发送邮件到[email protected]

\

本文是我对V5Node项目的总结,该项目的特性包括:

\
  1. 项目大多数的文件都是属于静态文件,只有数据部分存在动态请求。\
  2. 数据部分的请求都呈现为RESTful的特性。\

所以项目主要包含两个部分就是静态服务器和RESTful服务器。本文讲的是静态文件服务器部分。

\

既是一个新的项目,那么创建v5node目录是应该的。既是一个Node应用,创建一个app.js文件也是应该的。

\

我们的app.js文件里的结构很明确:

\
\var PORT = 8000;\var http = require('http');\var server = http.createServer(function (request, response) {\    // TODO\});\server.listen(PORT);\console.log(\"Server runing at port: \" + PORT + \".\");\
\

因为当前要实现的功能是静态文件服务器,那么以Apache为例,让我们回忆一下静态文件服务器都有哪些功能。

\

浏览器发送URL,服务端解析URL,对应到硬盘上的文件。如果文件存在,返回200状态码,并发送文件到浏览器端;如果文件不存在,返回404状态码,发送一个404的文件到浏览器端。

\

以下两图是Apache经典的两种状态。

\

博文共赏:Node.js静态文件服务器实战

\

博文共赏:Node.js静态文件服务器实战

\

现在需求已经明了,那么我们开始实现吧。

\

实现路由

\

路由部分的实现在《The Node Beginner Book》已经被描述过,此处不例外。

\

添加url模块是必要的,然后解析pathname。

\

以下是实现代码:

\
\var server = http.createServer(function (request, response) {\    var pathname = url.parse(request.url).pathname;\    response.write(pathname);\    response.end();\});
\

现在的代码是向浏览器端输出请求的路径,类似一个echo服务器。接下来我们为其添加输出对应文件的功能。

\

读取静态文件

\

为了不让用户在浏览器端通过请求/app.js查看到我们的代码,我们设定用户只能请求assets目录下的文件。服务器会将路径信息映射到assets目录。

\

涉及到了文件读取的这部分,自然不能避开fs(file system)这个模块。同样,涉及到了路径处理,path模块也是需要的。

\

我们通过path模块的path.exists方法来判断静态文件是否存在磁盘上。不存在我们直接响应给客户端404错误。

\

如果文件存在则调用fs.readFile方法读取文件。如果发生错误,我们响应给客户端500错误,表明存在内部错误。正常状态下则发送读取到的文件给客户端,表明200状态。

\
\var server = http.createServer(function (request, response) {\    var pathname = url.parse(request.url).pathname;\    var realPath = \"assets\" + pathname;\    path.exists(realPath, function (exists) {\        if (!exists) {\            response.writeHead(404, {\                'Content-Type': 'text/plain'\            });\\            response.write(\"This request URL \" + pathname + \" was not found on this server.\");\            response.end();\        } else {\            fs.readFile(realPath, \"binary\