A minor bug fix for hapi-swagger

 
Updated 25th December, 2013: The bug fix described below has been merged into the hapi-swagger codebase. The npm package hasn’t yet been updated but I expect it will be in the next few days.

Updated 26th December, 2013: The npm package has now been updated; version 0.0.4 contains this fix.

 

If you’ve recently spent any time at all building a RESTful API using Spumko’s HAPI then it’s more than likely that you’ve come across Swagger. Developed for use on the popular Wordnik site, Swagger is “a specification and complete framework implementation for describing, producing, consuming, and visualizing RESTful web services”. The beauty of the Swagger  approach is that with the hapi-swagger plugin and a few lines of code it’s possible to automatically generate comprehensive, living documentation for your API that is always in sync with your codebase updates… no more excuses for documentation trailing days or weeks behind code changes.

forms_js
Code extract showing the tags used to generate Swagger-based documentation.

 

The Problem

That’s the theory anyway. Unfortunately, there was (and still is) a fairly trivial bug in the hapi-swagger plugin that prevents the documentation being generated as it should.
In the file lib/index.js from line 55 onwards is a small block of code that ensures that Swagger documentation is generated for each defined route:


routes = routes.filter(function (item) {
if (request.query.path &&
item.path.indexOf('/' + request.query.path) !== 0 ) {
return false;
}
return item.settings.plugins['hapi-swagger'] !== false && item.method !== 'options';
 });

What this short snippet of code does is process the routes defined by your app one at a time and selects only those that match a value passed in as request.query.path. For example, if request.query.path equals ‘movies’ then this code will include all routes which begin with the string ‘/movies’. This would mean that we would then generate Swagger formatted documentation for the routes ‘/movies‘, ‘/movies/{id}’, ‘/movies/{id}/actors’ and so on, which is exactly what we want. Unfortunately it would also include routes such as ‘/moviescenes’ which we do not want.

It’s worth mentioning that an earlier version of this code appended an extra “/” symbol to the search string in line 57 so that, instead of ‘/movies’ the route would have to begin with ‘/movies/’. This prevented false positives like ‘/moviescenes’ but, unfortunately, also ignored the top level routes such as ‘/movies’.

The solution

The simplest way to make sure that all the matching routes and only the matching routes generate Swagger documentation is to replace the indexOf in line 57 with a search using a regular expression. With a regular expression, we are able to specify that, for example, only routes which begin ‘/movies/’ be selected (as they were originally) and routes that contain only ‘/movies’. In that way we can make sure we generate documentation for ‘/movies’, ‘/movies/’, ‘/movies/{id}’ and so on, but not ‘/moviescenes’.

The changed code is below (only line 57 has changed):


routes = routes.filter(function (item) {
if (request.query.path &&
item.path.search('^/' + request.query.path + '(/|$)') !== 0 ) {
return false;
}
return item.settings.plugins['hapi-swagger'] !== false && item.method !== 'options';
 });

I have submitted this bug fix to the hapi-swagger repo on Github but if you need it before it is approved and merged (assuming it is accepted) then you can edit the file directly or pull it from my fork of the repo (link below).

I’ve also created a jsFiddle that illustrates the difference between the indexOf approach and the search approach. You can use that to quickly try out some of your own routes.


More:

Validating a MongoDB object id

 
If you’re working with MongoDB then sooner or later you’re likely to hit an error when inserting or updating a document with a badly constructed Object Id.

For example:


db.mycol.insert({
  "_id": ObjectId("5289e30bcc93743934044d2Z",
  "name": "dvolr"
})

run in the Mongo shell will result in an “Error: invalid object id: not hex” message.

Of course, it’s better to catch this error before even attempting the database update.
This one line Javascript function uses a simple regular expression to check that the id is a 24-character hex string (i.e. only characters 0 to 9 and A to F). It will work in the browser and Node.js.


function isValidObjectID(str) {

  // A valid Object Id must be 24 hex characters
  return (/^[0-9a-fA-F]{24}$/).test(str);

}

// This one returns 'true'
alert( isValidObjectID('507f1f77bcf86cd799439011')

// This one returns false (notice the 'Z')
alert( isValidObjectID('507f1f77bcfZ6cd799439011')

I’ve also created a JSFiddle if you want to try it out with some other values.


More: