2

I have already added the codes for serving an image on my node server but it seems to not serve images in the HTML when connecting to Node. I have also external CSS and JS that are being served correctly. Here is the fragment of my code in Node (See below). Thank you in advance!

var server = http.createServer(function(req, res) {
    var pathname = url.parse(req.url).pathname;
    var ext = path.extname(pathname);
    var handler = handlers[req.url];
    if(ext) {
        if(ext === ".css"){
            res.writeHead(200, { "Content-Type" : "text/css" });
        }
        else if(ext === ".js") {
            res.writeHead(200, { "Content-Type" : "text/javascript" });
        }
        else if(ext === ".jpg") {
            res.writeHead(200, { "Content-Type" : "image/jpg" });
        }
        res.write(fs.readFileSync(__dirname + pathname, "utf8"));
        res.end();
    }
    else if(handler) {
        handler(req, res);
    }
    else {
        res.writeHead(404, { "Content-type" : "text/plain" });
        res.end();
    }
});
server.listen(80);
Cham
  • 131
  • 1
  • 10
  • 1
    Any error which you can see in the console like 404? – Aruna Nov 28 '16 at 04:51
  • 2
    `it seems to not serve images` - "seems to not" is very different from "does not" ... check the **browser** developer tools console or networks tab to see if *a)* a request is made, and *b)* what the response from your server actually is (both status and **content**) – Jaromanda X Nov 28 '16 at 04:54
  • 1
    This is unrelated, but you really should not just be blindly serving up files from disk based on user input (someone could request `/../../../../../`). Put all of your public files into some directory in whatever hierarchy you want, but verify that the final *resolved* path is not outside of that base public directory. – mscdex Nov 28 '16 at 05:05
  • 1
    I'd suggest you add a `console.log(__dirname + pathname)` and see if that is the desired filename. Plus you don't want to be reading a binary file with `utf8` encoding and you don't want to be using synchronous I/O either. Might want to read this [How to serve an image using nodejs](http://stackoverflow.com/questions/5823722/how-to-serve-an-image-using-nodejs). – jfriend00 Nov 28 '16 at 07:12
  • Aruna: No I don't get the error like that, but what I see in my html is when an image is note loaded. JaromandaX: Images are not serve, my apologies on my grammar, I will check on the console and network logs. mscdex: Okay that is noted. I just started learning this technology. jfriend00: I will remove the utf8 on my code and wll do a console log for that directory and path name. – Cham Nov 28 '16 at 13:27

1 Answers1

6

I've seen a lot of questions like this on Stack Overflow when someone tries to implement their own static file server instead of using Express or something that works, and fails to make it work. If you can implement your own static file server then do it. If you can't, then it should be a sign that maybe it's not a good idea. Update: See below for solutions without Express.

Problems

Just by glancing at your code code I already see several serious problems with it, including:

  1. Your code is insecure - it allows anyone to get any file on your system.

  2. Your code is blocking - it will grind to a halt as soon as you get any concurrent connections.

  3. Your code doesn't work for binary files - only for text files, and only those with UTF-8 encoding

  4. Your code doesn't work for uppercase filenames, .jpeg extension etc.

  5. Your code doesn't serve HTML files correctly

  6. Your code crashes when files don't exist instead of responding with proper code

Solution

Anyone who answers a question like this has two options: either put a lot of effort and time into fixing every one of the problems mentioned above (which rarely happens because it is not a trivial task and that's why all you see are comments mentioning one or two of those problems instead of answers) or you can explain how the task should be done properly instead of adding countless fixes to something that was not a good idea in the first place.

That having been said, what you can do to achieve your goal here in a secure and performant way is to put your static files (HTML, CSS, images etc.) into a directory, e.g. called html and use Express (or some other frameworks, see below) with a simple code like this:

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

var htmlPath = path.join(__dirname, 'html');

app.use(express.static(htmlPath));

var server = app.listen(80, function () {
    console.log('listening on port', server.address().port);
});

See the full example with explanation on GitHub:

I put this example on GitHub because there are a lot of questions on Stack Overflow related to problems that people have with serving static files in Node. It's open-source, you can adapt it to your own needs and use in your code.

For more info on Express, see:

Other options

Other frameworks that you can use to serve static files include:

Without a framework

If you still think that you don't want to use a high-level framework that does the job correctly and you want to roll your own solution, maybe for educational purposes, then see this answer:

It explains how to serve static images with:

  1. express.static (express built-in middleware, like in this answer)
  2. express (express but without express.static)
  3. connect (one level below than express)
  4. http (using Node's http module)
  5. net (not even using http module)

All of the examples posted are tested and work on Node versions 4, 5, 6 and 7.

Other related answers:

rsp
  • 107,747
  • 29
  • 201
  • 177
  • Your answer is really helpful much appreciated! I am only starting to work on this technology and my assignment is not use a framework and use only pure Javascript. I am not yet aware of the problems that my code is listed. I will check the links later to get more information. – Cham Nov 28 '16 at 13:27
  • I got it fixed by removing the "utf8" on res.write(fs.readFileSync(__dirname + pathname, "utf8")); – Cham Nov 28 '16 at 17:37
  • 1
    @Cham If you don't want to use a framework then see my updated answer and [this](http://stackoverflow.com/questions/5823722/how-to-serve-an-image-using-nodejs/40899767#40899767). Hope it helps. – rsp Dec 01 '16 at 10:05