Reputation: 43
I'm running into a weird problem when creating a simple web server in Nodejs
. The http server runs fine and accepts requests and responses like it should. However, for some reason it always wants to send a content-type:
of text/plain
for everything. For example, .js
and .css
files always come down as text/plain
whereas they should normally be sent as text/css
or application/javascript
. Chrome, the browser I'm using to test this, always complains about the MIME type of the resource:
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".
What this ultimately means is the css
is never applied to the page. I've added some logging and it appears that the http response is sending down the correct MIME type.
I've created a barebones version of what I'm doing. Hopefully someone can point out the flaw that I've coded:
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;
}
test-client.js
var div = document.getElementById('test');
div.innerHTML = 'test client ran successfully';
Upvotes: 4
Views: 4437
Reputation: 745
I ran into the same problem, however mine was caused slightly differently. I was initially using this method to set the Content_Type
:
res.writeHead(200, { 'Content_Type': contentType });
After replacing it with the following the errors disappeared:
res.setHeader('Content-Type',contentType)
Upvotes: 0
Reputation: 1
And you must made fs.readFile
wrapped by a closure, otherwise some file (especially the last file) will be read more than once, and others will not be read at all. And the contentType
will not be set as you wish. This is because of the callback strategy used by fs.readFile
. The problem does not appear when the html file just load one external file, but as the external files(css, js, png) loaded more than one it will appear as i pointed out above. (I cannot login with my gmail so I post as a guest)
So your code should make a little change as follows:
;(function (filename, contentType) {
fs.readFile(filename, function(err, file) {
// do the left stuff here
});
}(filename, contentType));
Upvotes: 0
Reputation: 12662
I think the issue is that you are using an unnecessary :
after Content-Type
when setting headers. You should either do response.setHeader('Content-Type',contentType);
or, which I think is even better, do this: response.writeHead(200,{'Content-Type':contentType});
Upvotes: 4