NodeJS中的基本静态文件服务器
我试图在nodejs中创build一个静态文件服务器,作为理解节点的一个练习,而不是一个完美的服务器。 我非常了解像Connect和node-static这样的项目,并且完全打算将这些库用于更多的生产就绪代码,但是我也想了解我正在使用的基础知识。 考虑到这一点,我编写了一个小的server.js:
var http = require('http'), url = require('url'), path = require('path'), fs = require('fs'); var mimeTypes = { "html": "text/html", "jpeg": "image/jpeg", "jpg": "image/jpeg", "png": "image/png", "js": "text/javascript", "css": "text/css"}; http.createServer(function(req, res) { var uri = url.parse(req.url).pathname; var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { console.log("not exists: " + filename); res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('404 Not Found\n'); res.end(); } var mimeType = mimeTypes[path.extname(filename).split(".")[1]]; res.writeHead(200, mimeType); var fileStream = fs.createReadStream(filename); fileStream.pipe(res); }); //end path.exists }).listen(1337);
我的问题是双重的
-
这是在节点创build和stream式传输基本html等的“正确”方式,还是有一个更好/更优雅/更强大的方法?
-
.pipe()在节点基本上只是做下面的?
。
var fileStream = fs.createReadStream(filename); fileStream.on('data', function (data) { res.write(data); }); fileStream.on('end', function() { res.end(); });
感谢大家!
-
您的基本服务器看起来不错,除了:
有一个
return
声明丢失。res.write('404 Not Found\n'); res.end(); return; // <- Don't forget to return here !!
和:
res.writeHead(200, mimeType);
应该:
res.writeHead(200, {'Content-Type':mimeType});
-
是的
pipe()
基本上是这样的,它也暂停/恢复源码stream(如果接收器速度较慢)。 这里是pipe()
函数的源代码: https : //github.com/joyent/node/blob/master/lib/stream.js
less即是多
只需在您的项目中首先使用命令提示符并使用
$ npm install express
然后写下你的app.js代码,如下所示:
var express = require('express'), app = express(), port = process.env.PORT || 4000; app.use(express.static(__dirname + '/public')); app.listen(port);
然后,您将创build一个“公共”文件夹放置您的文件。 我首先尝试了这种方法,但是你必须担心mimetypes,这些types只需要映射耗时的东西,然后担心响应types等。等等……不,谢谢。
我也喜欢理解发生了什么。
我注意到了你可能想要清理的代码中的一些东西:
-
当文件名指向一个目录时,它崩溃,因为存在是真的,它试图读取一个文件stream。 我用fs.lstatSync来确定目录的存在。
-
它没有正确使用HTTP响应代码(200,404等)
-
当MimeType正在被确定(来自文件扩展名)时,它没有在res.writeHead中正确设置(正如Stewe指出的那样)
-
要处理特殊字符,你可能想要使用uri
-
它盲目地遵循符号链接(可能是一个安全问题)
鉴于此,一些apache选项(FollowSymLinks,ShowIndexes等)开始变得更有意义。 我已经更新了简单文件服务器的代码,如下所示:
var http = require('http'), url = require('url'), path = require('path'), fs = require('fs'); var mimeTypes = { "html": "text/html", "jpeg": "image/jpeg", "jpg": "image/jpeg", "png": "image/png", "js": "text/javascript", "css": "text/css"}; http.createServer(function(req, res) { var uri = url.parse(req.url).pathname; var filename = path.join(process.cwd(), unescape(uri)); var stats; try { stats = fs.lstatSync(filename); // throws if path doesn't exist } catch (e) { res.writeHead(404, {'Content-Type': 'text/plain'}); res.write('404 Not Found\n'); res.end(); return; } if (stats.isFile()) { // path exists, is a file var mimeType = mimeTypes[path.extname(filename).split(".").reverse()[0]]; res.writeHead(200, {'Content-Type': mimeType} ); var fileStream = fs.createReadStream(filename); fileStream.pipe(res); } else if (stats.isDirectory()) { // path exists, is a directory res.writeHead(200, {'Content-Type': 'text/plain'}); res.write('Index of '+uri+'\n'); res.write('TODO, show index?\n'); res.end(); } else { // Symbolic link, other? // TODO: follow symlinks? security? res.writeHead(500, {'Content-Type': 'text/plain'}); res.write('500 Internal server error\n'); res.end(); } }).listen(1337);
这种模式如何避免单独检查文件是否存在
var fileStream = fs.createReadStream(filename); fileStream.on('error', function (error) { response.writeHead(404, { "Content-Type": "text/plain"}); response.end("file not found"); }); fileStream.on('open', function() { var mimeType = mimeTypes[path.extname(filename).split(".")[1]]; response.writeHead(200, {'Content-Type': mimeType}); }); fileStream.on('end', function() { console.log('sent file ' + filename); }); fileStream.pipe(response);
我根据@Jeff Ward的回答制作了一个带有额外function的httpServer函数
- custtom dir
- index.html返回如果请求=== dir
用法:
httpServer(dir).listen(port);
https://github.com/kenokabe/ConciseStaticHttpServer
谢谢。
var http = require('http') var fs = require('fs') var server = http.createServer(function (req, res) { res.writeHead(200, { 'content-type': 'text/plain' }) fs.createReadStream(process.argv[3]).pipe(res) }) server.listen(Number(process.argv[2]))
st模块使服务静态文件变得容易。 这里是README.md的摘录:
var mount = st({ path: __dirname + '/static', url: '/static' }) http.createServer(function(req, res) { var stHandled = mount(req, res); if (stHandled) return else res.end('this is not a static file') }).listen(1338)
@JasonSebring答案指出我正确的方向,但他的代码已经过时了。 这里是你如何使用最新的connect
版本。
var connect = require('connect'), serveStatic = require('serve-static'), serveIndex = require('serve-index'); var app = connect() .use(serveStatic('public')) .use(serveIndex('public', {'icons': true, 'view': 'details'})) .listen(3000);
在connect
GitHub仓库中还有其他可以使用的中间件。