2013-12-23 28 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));