javascript - Simple Nodejs web server always sends textplain css and js files - Stack Overflow

I'm running into a weird problem when creating a simple web server in Nodejs. The http server runs

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 e 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 plains 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';

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 e 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 plains 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';
Share Improve this question edited Dec 23, 2013 at 22:50 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked Dec 23, 2013 at 21:06 xzelaxzela 431 silver badge6 bronze badges 2
  • when setting headers, you don't really do it right. To the extent of my knowledge, you shouldn't use response.setHeader, instead do response.writeHead(200,{'Content-Type':'contentType'}); and also, in the error handler, for the options on writeHead you did {'Content-Type:','something-or/other'} but there shouldn't be that : after Content-Type: it should just be Content-Type – markasoftware Commented Dec 23, 2013 at 21:11
  • Thanks for wanting to mark the question as solved - however, on Stack Overflow, the tick is fine :). – halfer Commented Dec 23, 2013 at 22:51
Add a ment  | 

3 Answers 3

Reset to default 4

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

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 contentTypewill 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)); 

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)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745210801a4616826.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信