1

I'm in a bit of a predicament. I'm new to coding in general, and this is my assigned program for my JavaScript class this week. We are supposed to create a web server that serves files from a file system, that also implements Node modules. It must be able to read HTML, css, gif, and js resources. These files will be placed within the same folder as the script, under a /scripts and /html directory. Here is the logic I have tried to implement, however my terminal keeps telling me path.extname(resource) is an undefined function. It's quite ugly, I know, but I'm still trying to wrap my head around this concept. Any help would be great, I have been trying to figure this out for the past day.

'use strict';

// Load the file system module
var fs = require('fs');

// load the http module
var http = require('http');

// load the url module
var url = require('url');

// load the path module
var pathModule = require('path');


// The following function will be called when the server
// is handling a request

function servePage(request, response) {
    // get path name and remove '/'
    var path = url.parse(request.url).pathname.substring(1);

    // if path is an empty string
    if (path === '') {
        path = './html/home.html';
    }

    // Read the file asynchronously; HTML
    fs.readFile(path, function (err, content) {

        var extension = path.extname(path);

        switch (extension){
            case '.hmtl':
                response.writeHead(200,
                {'Content-Type': 'image/gif'});
            response.write(content); // Send file contents as response body
            response.end();
            break;

            case '.gif':
                response.writeHead(200,
                {'Content-Type': 'text/html; charset = UTF-8'});
            response.write(content); // Send file contents as response body
            response.end();
            break;

            case '.css':
                response.writeHead(200,
                {'Content-Type': 'text/css; charset = UTF-8'});
            response.write(content); // Send file contents as response body
            response.end();
            break;

            case '.js':
                response.writeHead(200,
                {'Content-Type': 'application/javascript; charset = UTF-8'});
            response.write(content); // Send file contents as response body
            response.end();
            break;

            case 'err':
            response.writeHead(404, 
                {'Content-Type': 'text/plain; charset = UTF-8'});
            response.write(err.message + 
                ' - The page requested was not found.');
            response.end(); // Done
            break;
        }



        /* }
        if (err) { // If there is an error, set the status code
            response.writeHead(404, 
                {'Content-Type': 'text/plain; charset = UTF-8'});
            response.write(err.message + 
                ' - The page requested was not found.');
            response.end(); // Done
            // else if the content was succesfully read
        } else {
            response.writeHead(200,
                {'Content-Type': 'text/html; charset = UTF-8'});
            response.write(content); // Send file contents as response body
            response.end();
        } */
    });
}







// create a server object
var server = http.createServer(servePage);
server.listen(8080);

console.log('Server running at http://localhost:8080');
3
  • 1
    That's because you require'd the path module into the pathModule variable. Use pathModule.extname(resource). Commented Jun 3, 2015 at 5:40
  • Beginner's tip: You should reduce your use of comments. Don't comment the immediately obvious, that's a waste of time and space - and it tricks you into reading the comments instead of the code when reasoning about your program. For your code sample that would mean you can get rid of every single comment, none of them adds any information. Commented Jun 3, 2015 at 5:55
  • Opposite tip: as a beginner, add all the comments you need in order to help visual processing. You can remove them when everything works, but it's understandable that code isn't directly transparent, if you aren't yet used to it. Comments have drawbacks, as @Tomalak mentioned, but I believe they're helping you as they were helping me. When you won't be anymore "new to coding in general" and you will handle more info and code in your head, then you can start following best practices about comments. Other devs might not like the aesthetic of it; and it's fine, for now. It's not runtime code. Commented Nov 23, 2021 at 12:30

3 Answers 3

3

Here is how I would restructure your code.

'use strict';
var fs = require('fs');
var http = require('http');
var url = require('url');
var path = require('path');

function getContentType(ext) {
    switch (ext.toLowerCase()) {
        case '.html': return 'text/html; charset=UTF-8';
        case '.gif':  return 'image/gif';
        case '.css':  return 'text/css; charset=UTF-8';
        case '.js':   return 'application/javascript; charset=UTF-8';
        default:      return 'text/plain; charset=UTF-8';
    }
}

var server = http.createServer(function (request, response) {
    // This is dangerous.
    var filePath = url.parse(request.url).pathname.substring(1);
    if (filePath === '') {
        filePath = './html/home.html';
    }

    fs.readFile(filePath, function (err, content) {
        var statusCode = 200,
            headers = {
                'Content-Type': getContentType(path.extname(filePath))
            };

        if (err) {
            statusCode = 404;
            headers['Content-Type'] = getContentType('.txt');
            content = 'The page requested was not found.\n\n' + err.message;
        }

        response.writeHead(statusCode, headers);
        response.write(content);
        response.end();
        console.log('' + statusCode + ': ' + filePath);
    });
});

server.listen(8080);
console.log('Server running at http://localhost:8080');

Note that this

var filePath = url.parse(request.url).pathname.substring(1);

is dangerous.
Think what happens when somebody requests /../../etc/passwd.

Sign up to request clarification or add additional context in comments.

2 Comments

thank you for this, however when I use your code, instead of loading the .html documents, it displays the content...
@demboiz Try again. Compare my changes.
2

Please use express framework it will make your work easy.

var express = require('express');
app.use("/",  express.static(__dirname + '/client/'));
app.listen(3000,function(){
console.log("App Started on PORT 3000");
});

here your client folder will contain all the files i.e gif, html etc.

Comments

1

Your path variable is assigned to a string while your 'path' module is assigned to a pathModule

So there is no function to call on the path (because it is a string)

you should change it to pathModule.extname();

4 Comments

that was such a silly error... I have just changed that, but the server still doesn't load. Is there any other flaws in my logic that you can see? Prior to adding the switch loop, the server would load the empty string path, but now it just refuses to connect :\
@demboiz could you give more detail on the error? like what is the error message
so in the case that I change the last switch statement to default, I get an error that reads "TypeError: Cannot read property 'message' of null"; in the case that I leave it as case "err", the server does not load. Either way, none of my resources load.
@demboiz you can't change it to "default" since you are asking the 'err' object's 'message' method. As for the resource not loading, it should be that the fs.readFile(path, function(err,content)) will read the file from (path) and pass (err, content) to the callback function. When a file is already read, there is no point doing switch case to change the type of the file. You can refer to the docs of the readFile: nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.