Node.js + Serve Static Files with RESTIFY
Asked Answered
R

2

9

I have a multi-level collection of .html, .js, .png, .css, etc files in a site. A peek at my site hiearchy looks like the following:

index.html
child1
  index.html
  page1.html
  page2.html
  ...
child2
  grandchild1
    index.html
  grandchild2
    index.html
  index.html
  page1.html
  page2.html
resources
  css
    myTheme.css
  img 
    logo.png
    profile.png
  js
    jquery.js
    ...
...

I am migrating this to run under Node.js. I have been told I MUST use RESTIFY. Currently, I've written the following for my server:

var restify = require('restify');
var fs = require('fs');
var mime = require('mime');

var server = restify.createServer({
    name: 'Demo',
    version: '1.0.0'
});

server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());

server.get('/', loadStaticFile);

server.get('/echo/:name', function (req, res, next) {
    res.send(req.params);
    return next();
});

server.listen(2000, function () {
    console.log('Server Started');
});

function loadStaticFile(req, res, next) {
    var filePath = __dirname + getFileName(req);
    console.log("Returning " + filePath);

    fs.readFile(filePath, function(err, data) {
      if (err) {
        res.writeHead(500);
        res.end("");
        next(err);
        return;
      }

      res.contentType = mime.lookup(filename);
      res.writeHead(200);
      res.end(data);

      return next();
    });
}

function getFileName(req) {
    var filename = "";
    if (req.url.indexOf("/") == (req.url.length-1)) {
      filename = req.url + "index.html";
    } else {
      console.log("What Now?");
    }
    return filename;
}

With this code, I can successfully load index.html. However, my index.html file references some JavaScript, image files, and style sheets. I can see via Fiddler that that these files are being requested. However, in my node.js console window, I never see "Returing [js|css|png filename]". Its like my node.js web server returns index.html and that's it.

What am I doing wrong?

Retriever answered 11/10, 2013 at 14:46 Comment(1)
I fail to see the point in using restify if you are adding non ReST features like static file serving. express offers everything you need and more, with the addition of better docs, proven stability in production, and community support.Salinometer
A
5

Do any of your served files contain relative paths (say ../abc.js)? You have to use path.resolve() to get the real path for fs.readFile().

Anyway there are a lot of pitfalls in serving files:

  • invalid url (400)
  • file not found (404)
  • escape sequence (url encoding)
  • fs.read() read files into memory (by @robertklep)
  • etc

You can use existing static file serving middleware.
I've been using Ecstatic, AFAIK it handles those issues properly.

Try

server.use(ecstatic({ root: __dirname + '/' }));

If that fails you can refer to this to stack Restify on top of Connect/Express.

Altruist answered 11/10, 2013 at 17:1 Comment(1)
+1 for suggesting to use static middleware (another issue with fs.readFile is that it reads files into memory first)Hawks
B
16

The latest versions of restify has builtin middleware serveStatic() middleware that will do this for you.

from a http://mcavage.me/node-restify/#Server-API

server.get(/\/docs\/public\/?.*/, restify.serveStatic({
  directory: './public'
}));

for more detailed example:

http://mushfiq.me/2013/11/02/serving-static-files-using-restify/

Boche answered 18/11, 2013 at 23:48 Comment(0)
A
5

Do any of your served files contain relative paths (say ../abc.js)? You have to use path.resolve() to get the real path for fs.readFile().

Anyway there are a lot of pitfalls in serving files:

  • invalid url (400)
  • file not found (404)
  • escape sequence (url encoding)
  • fs.read() read files into memory (by @robertklep)
  • etc

You can use existing static file serving middleware.
I've been using Ecstatic, AFAIK it handles those issues properly.

Try

server.use(ecstatic({ root: __dirname + '/' }));

If that fails you can refer to this to stack Restify on top of Connect/Express.

Altruist answered 11/10, 2013 at 17:1 Comment(1)
+1 for suggesting to use static middleware (another issue with fs.readFile is that it reads files into memory first)Hawks

© 2022 - 2024 — McMap. All rights reserved.