Originally Posted by
MutantJohn
you can use the Express module to handle GET requests with a regular expression.
Finally! I tried showing you how that worked and you just said it looked complicated lol!
I'm currently doing my first real paid development work, and NodeJS has come through in everything I've wanted from it so far: routing, templating, form parsing, websocket based chat rooms, and even sending email. There are still many aspects that I've never looked into, like how node handles databases etc, but for everything that I've needed, it's been able to do.
I've got a few gripes with it too about the lack of good documentation, especially for the 3rd party modules.
That said though, I actually learn a lot faster by poking around inside the modules in interactive mode than I would reading documentation. For instance I mapped out all of the socket.io modules by making many calls like this (interactive mode):
Code:
> var http = require("http");
undefined
> var sockio = require("socket.io");
undefined
> var server = http.createServer(function () {});
undefined
> var io = sockio.listen(server);
undefined
> console.dir(io);
{ nsps:
{ '/':
{ name: '/',
server: [Circular],
/* --- EDITED DOWN --- */
maxHttpBufferSize: 100000000,
transports: [ 'polling', 'websocket' ],
allowUpgrades: true,
allowRequest: [Function],
cookie: 'io',
ws:
{ domain: null,
_events: {},
_maxListeners: 10,
options: [Object],
path: null,
clients: [] },
_events: { connection: [Function] } } }
undefined
>
So I would recommend doing that if you can't find reliable documentation for some module. It's one of the greatest strengths of NodeJS.
I haven't used Jade myself, but I understand it has methods that allow it to be used as middleware by Express more easily than other template engines like Handlebars (that's the one I'm researching). From what I remember of Jade, people complain about it's steep learning curve, but credit it with having a lot of features.
Express works quite well though. I don't really enjoy the "middleware" architecture, but it's simple enough to make work.
Just make sure to make a dependency file that specifies the current versions of which modules you are using, because NodeJS module developers break backwards compatibility all the time, so you can't rely on correct behaviour if you always install the newest version.
I thought you might be interested, that I'm writing a very similar thing to make a client side picture slide show with a requested number of random pictures for the site. I had only worked on it for about an hour before getting on here, but it's nearly done. The one difference is that I know where the folder is, and I'm not templating here, but just making a JSON array of image locations:
Code:
// Just the request handler, it's wrapped in a closure.
return function (req, res) {
// Parse the number of requested pictures, from the query string part of the url
// Default to 10 pictures if the query is invalid
var query = url.parse(req.url).query,
parsed = typeof query === "string" ? qs.parse(query.toLowerCase()) : null,
numberRequested = (parsed.number && parseInt(parsed.number, 10)) || 10;
console.log("Got image request: " + req.url);
console.log((parsed.number ? "The query was a valid number: " + parsed.number + "." : "The query was invalid defaulting to : " + numberRequested));
// Read the directory with the images, create an array of random images either:
// 1. The number of images requested
// 2. The number of images in the directory (if requested number was greater)
fs.readdir(__dirname + publicDir + relativeDir, function (err, list) {
var maxImages = 0,
candidate = null,
result = [];
if (!err) {
console.log("Available images: " + list + "\n");
try {
maxImages = Math.min(numberRequested, list.length);
// Loop through list and collect requested number of unique images
while (result.length < maxImages) {
candidate = getRandomElement(list);
if (result.indexOf(candidate) === -1) {
result.push(candidate);
}
}
// Convert the resulting image paths to a JSON string,
// prepend the relative directory,
// and inform the client of type and length, and send
result = JSON.stringify(result.map(prependRelativeDir));
console.log("Sending images: " + result);
res.writeHead(200, {"Content-Type": "application/json", "Content-Length": (new Buffer(result)).length});
res.write(result);
res.end();
} catch (e) {
res.writeHead(500);
res.write("Server: Error: Error in sending list of images");
res.end();
throw e;
}
} else {
// Filled in later
throw err;
}
});
};
Remember to use the "writeHead" of the http response to specify the status code of responses. Also I couldn't see if you are using it, but you will probably be interested to know that the HTTP response object available inside Express methods has a "sendFile" method that will just send a file for you, which is way easier than the equivalent bare bones NodeJS approach.
Originally Posted by
MutantJohn
Code:
throw new MemeError("We got a bad-ass over here dot PNG");
PS: I've had an idea for a module that would make using the bare HTTP response object easier, I haven't worked on it yet, but the basic idea is like this:
Code:
function respond (res) {
return (new function (res, done) {
this.withJSON = function (obj) {
if (!done) {
var json = JSON.stringify(obj);
res.writeHead(200, {"Content-Length": (new Buffer(json)).length, "Content-Type": "application/json"});
res.write(json);
res.end();
done = true;
}
return this;
};
this.withError = function (error) {
if (!done) {
res.writeHead(500);
res.write(error || "Server Error.");
res.end();
done = true;
}
return this;
};
}(res, false));
}