nodejs文件系统在第一个http响应后不会读取文件



我正在制作一个简单的http node.js服务器,只需让它发送web上最常见的文件(HTMLJavaScriptCSS)。

所以我只是制作节点文件,只测试HTML文件,这很好,但当我试图让它发送JavaScriptCSS文件时,服务器会返回一个错误并关闭。

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;
  }
}

最新更新