我正在制作一个简单的http
node.js
服务器,只需让它发送web上最常见的文件(HTML
、JavaScript
、CSS
)。
所以我只是制作节点文件,只测试HTML
文件,这很好,但当我试图让它发送JavaScript
或CSS
文件时,服务器会返回一个错误并关闭。
main.js
/*
* Main node.js server file
*/
// Load all modules
console.log('Loading modules');
var http = require('http'),
fs = require('fs'),
file = require('./bin/file.js');
// Load config file
console.log('Loading configuration file');
var config = fs.readFileSync('./config.json');
var config = JSON.parse(config);
// Config http server
var host = http.createServer(function(request, response)
{
console.log('requesting: ', request.url);
var view = file.read(request.url);
response.writeHead(view.status, view.head);
response.write(view.content);
response.end();
});
// Start server
if(host.listen(config.port))
console.log('Http server initialized on port:', config.port);
以防万一,config.json只包含端口和web文件目录
file.js
// Load the required modules
var fs = require('fs');
// Load configuration
var config = fs.readFileSync('config.json');
var config = JSON.parse(config);
// Export module function
module.exports = {
read: function(file)
{
if(file == '/')
return loadFile('/index.html');
}
};
// Load the requested file
function loadFile(file)
{
var req = fs.readFileSync(config.dirFiles + file);
var result = {};
if(!req)
{
result = {
status: 404,
head: {'Content-Type': 'text/plain'},
content: 'The requested view does not exist'
};
}
else
{
result = {
status: 200,
head: {'Content-Type': getMIME(file)},
content: req
};
}
return result;
}
// Detect MIME file type
function getMIME(file)
{
var regex = /(.css|.html|.js)/;
var ext = regex.exec(file);
var MIME = '';
switch(ext[1])
{
case '.js':
MIME = 'text/javascript';
break;
case '.css':
MIME = 'text/css';
break;
case '.html':
MIME = 'text/html';
break;
}
return MIME;
}
在请求CSS
文件时,服务器告诉view.status属性未定义,这可能是因为正在读取synchronous
文件,但我不知道还有什么其他方法可以执行
这里有一些问题,但主要问题是您只阅读过index.html
。因此,当请求路径与/
不匹配时,从read()
返回undefined
。然后,在您的请求处理程序中,您基本上尝试读取显然不存在的undefined.status
。
另一个问题是,你真的不应该这样做同步读取。不仅用法不正确(fs.*Sync
方法抛出异常,而不是对任何类型的错误(包括"找不到文件"错误)返回false-y值),而且异步执行可以提供更好的并发性,因为在文件读取完成之前不会阻止其他请求。
第三个问题是,如果请求的文件与任何支持的扩展名都不匹配,getMIME()
不会返回默认的mime类型。
以下是一个解决上述问题的示例解决方案:
main.js:
// ...
var host = http.createServer(function(request, response)
{
console.log('requesting: ', request.url);
var view = file.read(request.url);
response.writeHead(view.status, view.head);
if (view.stream)
view.stream.pipe(response);
else
response.end(view.content);
});
// ...
file.js:
var path = require('path');
// ...
module.exports = {
read: function(file)
{
if (file == '/')
return loadFile('/index.html');
return loadFile(file);
}
};
// Load the requested file
function loadFile(file)
{
var loc = path.normalize(config.dirFiles + file);
// check for malicious requests to files outside of `config.dirFiles`
if (loc.indexOf(config.dirFiles) === 0 && fileExists(loc)) {
return {
status: 200,
head: {'Content-Type': getMIME(file)},
stream: fs.createReadStream(loc)
};
}
return {
status: 404,
head: {'Content-Type': 'text/plain'},
content: 'The requested view does not exist'
};
}
// Detect MIME file type
function getMIME(file)
{
var regex = /(.css|.html|.js)/;
var ext = regex.exec(file);
var MIME = '';
switch(ext[1])
{
case '.js':
MIME = 'text/javascript';
break;
case '.css':
MIME = 'text/css';
break;
case '.html':
MIME = 'text/html';
break;
default:
MIME = 'text/plain';
}
return MIME;
}
function fileExists(filename) {
try {
var stats = fs.statSync(filename);
return stats.isFile();
} catch (ex) {
return false;
}
}