Alexander Mills
Alexander Mills

Reputation: 100010

Simple Node.js server without Express - piping HTML files to response

I am trying my hand at making a simple Node.js server without Express and this where I actually learn a bit more about the down and dirty of actually server files and data on requests based on paths request and basic HTTP stuff.

I have this straightforward server like so:

 var http = require('http');

const PORT = 6969;

var allRoutes = require('./routes/all');

var server = http.createServer(allRoutes);

server.listen(PORT, function () {
    console.log("Server listening on: http://localhost:%s", PORT);
});

and then I have one "middleware" function like so that handles all requests:

var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');

function handleRequest(req, res) {

    var requestUrl = url.parse(req.url);


    var fsPath;
    if (requestUrl.pathname === '/') {
        fsPath = path.resolve(appRootPath + '/view/index.html');
    }
    else {
        fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
    }

    fs.stat(fsPath, function (err, stat) {

        if (err) {
            console.log('error occurred...' + err);
            return end(req, res);
        }

        try {
            if (stat.isFile()) {
                res.writeHead(200);
                fs.createReadStream(fsPath).pipe(res);
            }
            else {
                res.writeHead(500);
            }
        }
        finally {
            end(req, res);
        }
    });
}


function end(req, res) {
    res.end();
}


module.exports = handleRequest;

the problem I am having is that my function doesn't seem to pipe the response to the browser. The browser shows no evidence of the data come from index.html, which is a barebones .html HTML5 file.

I stole the example, and am surprised it's not really working. Anyone have an idea? I know for sure that the fs.stat function is not experiencing an error and then it is streaming the index.html file, it just doesn't seem to be streaming to the right place...

Upvotes: 1

Views: 3001

Answers (1)

jfriend00
jfriend00

Reputation: 707318

For starters:

if (requestUrl.pathname = '/')

should be:

if (requestUrl.pathname === '/')

Your code was assigning, not comparing.


In addition, the .pipe() is asynchronous, but you are calling res.end() BEFORE it gets to do it's job in your finally{} block which closes the response stream and stops your pipe from doing anything. By default .pipe() will close the write stream by itself, so you don't need the res.end() at all when using .pipe().

You can change the code to this:

var url = require('url');
var fs = require('fs');
var appRootPath = require('app-root-path');
var path = require('path');

function handleRequest(req, res) {

    var requestUrl = url.parse(req.url);


    var fsPath;
    if (requestUrl.pathname === '/') {
        fsPath = path.resolve(appRootPath + '/view/index.html');
    }
    else {
        fsPath = path.resolve(appRootPath + '/view/' + requestUrl.pathname);
    }

    fs.stat(fsPath, function (err, stat) {

        if (err) {
            console.log('error occurred...' + err);
            return end(req, res);
        }

        try {
            if (stat.isFile()) {
                res.writeHead(200);
                fs.createReadStream(fsPath).pipe(res);
            }
            else {
                res.writeHead(500);
                end(req.res);
            }
        }
        catch(e) {
            end(req, res);
        }
    });
}


function end(req, res) {
    res.end();
}


module.exports = handleRequest;

Upvotes: 6

Related Questions