2013-12-23 31 views
4

Nodejs中创建简单的Web服务器时,我遇到了一个奇怪的问题。 http服务器正常运行并接受像它应该的请求和响应。但是,由于某种原因,它总是希望发送content-type:text/plain的一切。例如,.js.css文件总是以text/plain的形式出现,而它们通常应作为text/cssapplication/javascript发送。 Chrome浏览器,我使用的测试这个浏览器,总是抱怨MIME类型的资源:Simple Nodejs Web服务器总是发送文本/纯CSS和js文件

Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost:3000/test.css".

Resource interpreted as Script but transferred with MIME type text/plain: "http://localhost:3000/test-client.js".

什么这最终意味着是css永远不会应用到该页面。我添加了一些日志记录,看起来http响应正在发送正确的MIME类型。

我创建了一个我正在做的准系统版本。希望有人能指出我编写的缺陷:

test.js

var http = require('http'), 
    fs = require('fs'), 
    url = require('url'), 
    path = require('path'); 
var contentTypes = { 
    '.html': 'text/html', 
    '.css': "text/css", 
    '.js': 'application/javascript' 
}; 
http.createServer(function(request, response) { 
    // get file based on pathname 
    var uri = url.parse(request.url).pathname, 
     filename = path.join(__dirname, uri); 
    fs.exists(filename, function(exists) { 
     // if root directory, append test.html 
     if (fs.statSync(filename).isDirectory()) { 
      filename += 'test.html'; 
     } 
     // figure out MIME type by file ext 
     var contentType = contentTypes[path.extname(filename)]; 
     fs.readFile(filename, function(err, file) { 
      // errors? 
      if (err) { 
       response.writeHead(404, {'Content-type:': 'text/plain'}); 
       response.write(err + "\n"); 
       response.end(); 
      } else { 
       console.log('MIME TYPE for: ', filename , contentType); 
       response.setHeader('Content-Type:', contentType); 
       response.writeHead(200); 
       response.write(file); 
       response.end(); 
      } 
     }); 
    }); 
}).listen(3000, function(){ 
    console.log("server started and listening on port 3000"); 
}); 

的test.html

<!DOCTYPE html> 
<html> 
    <head> 
     <link rel="stylesheet" href="test.css" type="text/css" /> 
    </head> 
    <body> 
     <h1>Test</h1> 
     <div id="test"></div> 
     <script type="text/javascript" src="test-client.js"></script> 
    </body> 
</html> 

test.css

h1 { 
    color: red; 
} 

测试client.js

var div = document.getElementById('test'); 
div.innerHTML = 'test client ran successfully'; 
+0

设置标题时,你真的不这样做的权利。据我所知,你不应该使用'response.setHeader',而应该使用'response.writeHead(200,{'Content-Type':'contentType'});'并且在错误处理程序中为在'writeHead'上的选项你做了{Content-Type:','something-or/other'},但不应该在'Content-Type'后面加':'它应该是'Content-类型' – Markasoftware

+0

感谢您想要将问题标记为已解决 - 但是,在堆栈溢出时,打勾很好':)'。 – halfer

回答

4

我认为这个问题是您正在设置头时,使用不必要的:Content-Type后。您应该做的response.setHeader('Content-Type',contentType);或者,我认为这是更好的,这样做:response.writeHead(200,{'Content-Type':contentType});

+0

w00t! **非常感谢!**这就是问题所在。 – xzela

0

而且你必须做出fs.readFile通过封闭包裹,否则某些文件(特别是最后一个文件)将被读取一次以上,和其他人将不会被读取。并且contentType将不会根据您的意愿进行设置。这是因为fs.readFile使用的回调策略。当html文件只加载一个外部文件时,问题不会出现,但是当外部文件(css,js,png)加载多个文件时,它会按我上面指出的那样出现。 (我不能用我的Gmail登录,所以我张贴作为嘉宾)

所以,你的代码应该稍作改动如下:

;(function (filename, contentType) { 

    fs.readFile(filename, function(err, file) { 
     // do the left stuff here 
    }); 

}(filename, contentType));