Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple node.js server that sends html+css as response

I've created basic http server that sends html file as response. How can I send css file as well so client using browser will see a html using css ?

The code I have:

var http = require('http');

var fs = require('fs');
var htmlFile;

fs.readFile('./AppClient.html', function(err, data) {
    if (err){
        throw err;
    }
    htmlFile = data;
});



var server = http.createServer(function (request, response) {
      response.writeHead(200, {"Content-Type": "text/html"});
      response.end(htmlFile);
    });

//Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);


console.log("Server running at http://127.0.0.1:8000/");

What I have tried(it seems it does not work - client sees only css file content here):

var http = require('http');

var fs = require('fs');
var htmlFile;
var cssFile;

fs.readFile('./AppClient.html', function(err, data) {
    if (err){
        throw err;
    }
    htmlFile = data;
});

fs.readFile('./AppClientStyle.css', function(err, data) {
    if (err){
        throw err;
    }
    cssFile = data;
});

var server = http.createServer(function (request, response) {
      response.writeHead(200, {"Content-Type": "text/css"});
      response.write(cssFile);
      response.end();

      response.writeHead(200, {"Content-Type": "text/html"});
      response.write(htmlFile);
      response.end();
    });

//Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);


console.log("Server running at http://127.0.0.1:8000/");

html file:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" type="text/css" href="AppClientStyle.css">
</head>
<body>


<div class=middleScreen>

<p id="p1">Random text</p>

</div>

</body>
</html>

css file :

@CHARSET "UTF-8";

.middleScreen{
    text-align:center;
    margin-top:10%;
}

I don't want to use express here(it is just for learning purpose)

like image 788
kiluk876 Avatar asked Mar 03 '15 00:03

kiluk876


1 Answers

What you have written in your first snippet is a web server that responds with the body of your HTML file regardless of what URI the browser requests.

That's all nice and well, but then with the second snippet, you're trying to send a second document to a closed response handle. To understand why this doesn't work, you have to understand how HTTP works. HTTP is (for the most part) a request->response type protocol. That is, the browser asks for something and the server sends that thing, or an error message of some sort, back to the browser. (I'll skip over keep-alive and methods that allow the server to push content to the browser--those are all far beyond the simple learning purpose you seem to have in mind here.) Suffice it to say that it is inappropriate to send a second response to the browser when it hasn't asked for it.

So how do you get the browser to ask for a second document? Well, that's easy enough... in your HTML file you probably have a <link rel="stylesheet" href="AppClientStyle.css"> tag. This will cause the browser to make a request to your server asking it for AppClientStyle.css. You can handle this by adding a switch or if to your createServer code to perform a different action based on the URL the browser requests.

var server = http.createServer(function (request, response) {
    switch (request.url) {
        case "/AppClientStyle.css" :
            response.writeHead(200, {"Content-Type": "text/css"});
            response.write(cssFile);
            break;
        default :    
            response.writeHead(200, {"Content-Type": "text/html"});
            response.write(htmlFile);
    });
    response.end();
}

So, first, when you access your server at http://localhost:8000 you will be sent your html file. Then the contents of that file will trigger the browser to ask for http://localhost:8000/AppClientStyle.css

Note that you can make your server far more flexible by serving any file that exists in your project directory:

var server = http.createServer(function (request, response) {
    fs.readFile('./' + request.url, function(err, data) {
        if (!err) {
            var dotoffset = request.url.lastIndexOf('.');
            var mimetype = dotoffset == -1
                            ? 'text/plain'
                            : {
                                '.html' : 'text/html',
                                '.ico' : 'image/x-icon',
                                '.jpg' : 'image/jpeg',
                                '.png' : 'image/png',
                                '.gif' : 'image/gif',
                                '.css' : 'text/css',
                                '.js' : 'text/javascript'
                                }[ request.url.substr(dotoffset) ];
            response.setHeader('Content-type' , mimetype);
            response.end(data);
            console.log( request.url, mimetype );
        } else {
            console.log ('file not found: ' + request.url);
            response.writeHead(404, "Not Found");
            response.end();
        }
    });
})                         

Start this in the same directory as your HTML and CSS files. The above is simplistic, error-prone and INSECURE. But it should be sufficient for your own learning or local development purposes.

Keep in mind that all the above is far less succinct than just using Express. In fact, I'm not sure why you wouldn't want to use Express, so I'm going to try to convince you to try it:

$ npm install express
$ mkdir www
$ mv AppClientStyle.css www/
$ mv AppClient.html www/index.html

Your script will look like: (Borrowed from Express Hello World)

var express = require('express')
var app = express()

app.use(express.static('www'));

var server = app.listen(8000, function () {

    var host = server.address().address
    var port = server.address().port

    console.log('Express app listening at http://%s:%s', host, port)

})

Then run your script and point your browser to http://localhost:8000. It really is that painless.

like image 141
Andy Zarzycki Avatar answered Sep 21 '22 21:09

Andy Zarzycki