Hi, I'm Tom; around the web I'm phuu. I write code and work at LeftLogic in Brighton.
We should talk.

More about me →

casper: helpers and handlers for Express

Hot on the heels of distra, here’s another little something for your toolbox! Watch the intro video, or check out the documentation. Either way, enjoy…

casper is a set of helpers and handlers for building JSONP APIs in Express.

All casper’s methods return a function that can be used in the Express callback chain, or as callbacks for methods that retrieve data, which would typically be a database.

Install

Install casper using npm:

npm install casper

Example usage

The following examples assume that you’ve got the following set up:


// an instance of express() (app) is available
var app = express();

// Grab casper
var casper = require('casper');

Basic handlers

Send an empty object:


// res.jsonp({}) is sent
app.get('/', casper.noop());

Or return some custom data:


// res.jsonp({ hello: 'world' }) is sent
app.get('/',
  casper.noop({
    hello: 'world'
  }));

Database callbacks

casper.db

casper.db returns a function to be used as a database callback. It assumes the first argument is an err and the second is the data is has to send – an array or an object.

It takes Express’ req and res as arguments:


casper.db(req, res)

For example:


app.get('/',
  function (req, res) {
    YourModel
      .find()
      .exec(casper.db(req, res));
  });

It can also take a callback which, if present, is called instead of sending data directly back to the client.

With a callback:


app.get('/',
  function (req, res) {
    YourModel
      .find()
      .exec(casper.db(req, res, function (err, data) {
        // Do something with data
      }));
  });

If it is passed an error, it will pass that on to the client with a 500 status code. If it recieves no data, or an empty array, it will return the data it recieved with a 404 status.

Checks & filters

Casper also has some useful checks & filters to help you ensure the data you’re recieving is what you’re expecting.

capser.check.body

Check for the presence of data in the body using a key:

For the following, assume the body is { testKey: "Hello" }


// calls next() becuase present
app.get('/',
  casper.check.body('testKey'),
  casper.noop());

If the data is missing from the body it sends a 400 error, detailing the missing parameter:


app.get('/',
  casper.check.body('nonExistantKey'),
  casper.noop());

// results in
res.jsonp(400, { error: 'Missing nonExistantKey from body.' });

capser.rm.body

Remove a key from the body:


// body is { testKey: "Hello", otherKey: "World" }
app.get('/',
  casper.rm('testKey'),
  casper.noop());

// afterwards body is { otherKey: "World" }

casper.allow.body

Whitelist a key or array of keys allowed on the body.


// body is { testKey: "Hello", otherKey: "World" }
app.get('/',
  casper.allow.body('otherKey'),
  casper.noop());

// afterwards body is { test: "Hello" }

With an array:


// body is { testKey: "Hello", otherKey: "World", unwantedKey: "World" }
app.get('/',
  casper.allow.body(['testKey', 'otherKey']),
  casper.noop());

// afterwards body is { testKey: "Hello", otherKey: "World" }

Feedback welcome!

As ever, I hope casper is useful to you! If you’ve got any feedback, bugs or ideas then let me know on Twitter or, even better, on GitHub.

distra: static server & reverse proxy

Here’s an introduction to an project I open-sourced recently: distra. There’s a video, and then a short article about it.

distra is a tool for building websites. Use it to serve static files and directories, and to give servers running on your computer nice URLs. You can set up hosts and routes (directories or proxy targets) using JSON, and then feel like a boss.

It also adds to your hosts file (safely) so you never have worry about that either!

Why?

I had so many servers, particularly serving static files, that I never knew what was being served and on which port. So I built this so I’d never have to care again… and neither will you.

Install

distra requires:

  • OS X (yeah, sorry)
  • Node
  • npm

In your terminal:


> npm install -g distra
> distra

Wahey! You’re up.

But it won’t do much yet – you need to configure it.

Configuration

distra is configured from the .distra.json file in your home directory, but you don’t ever have to touch this file if you don’t want to.

Adding a host

To add a host, use distra add.


> distra add [host] [directory or url]

The host and directory or url are both optional. If you omit the directory or url distra will serve your current directory.

If you omit both, distra will serve the current directory with the name of the directory as the host.

Try it:

Head to a directory with some .html files in it, lets say it’s called website.


> distra add

Assuming distra is started (just use distra), you will find that you can go to http://website:9876/ and access those files.

distra is servering the website directory from the URL http://website:9876/. Neat, huh?

Note: If you’re running distra without sudo (so it’s not running on port 80), then you’ll need to add all of these URLs to your hostsfile. To aviod this, run distra on port 80. How to do this is outlined in the ‘tips’ section.

Removing a host

To remove a host, use distra rm.


> distra rm [host]

Again, host is optional - by default, it will just use the directory name.

The config file

The config file will generally be found at ~/.distra.json.

Here’s an example.


{
  "mysite.dev":   "localhost:4000",
  "project":      "/Users/you/sites/project"
}

In the example above, requests made to http://mysite.dev/ will be proxied through to the server running on port 4000 (a Jekyll server, perhaps). Requests made to project will be served static files from the directory specified.

You can view your current config using distra:


> distra config

Tips

Here’s a couple of tips to help you out:

Ports

You can specify the port on which you want distra to start.


> distra 1337

Portsaway!

I recommend starting distra on port 80 so you don’t have to mess around with ports and your hostsfile!


> sudo distra 80

Finally

distra has become an integral part of my workflow – let me know if you use it, like it or come across any bugs!

Keeping Open-Source Secrets

Often with an open-source project you need to keep private configuration secret - it can’t be shared alongside the code. This can be anything that dictates the running of the app – like client secrets for a 3rd party API – that’s important to keep safe from potentially malicious uses.

Ways of keeping this data away from prying eyes may not be immediately obvious, but here’s a few options to get you started.

.gitignore

One way is to use a config file that’s never commited into the repository. You might use JSON and tell your open source users that they need to create their own to run the app:


{
    "db": "mongodb://localhost:27017/some-database",
    "twitter": {
        "client_id": "YOUR_CLIENT_ID",
        "client_secret": "YOUR_CLIENT_SECRET"
    }
}

And then import it into the project (here using Node):


// Create your own config file to run this app
var config = require('./config.json');

To make sure this file is never committed, make sure to ignore the file. In Git, this is done with a .gitignore file that goes in the root of your repo:


# ignore config file
config.json

It’s also worth providing a sample configuration file to help others out – you could call it config.example.json. Something like the above example is non-specific enough to work nicely.

This method works very well if you have direct access to the filesystem of the server (‘environment’) because you can update the config file manually. It doesn’t work so well if your app is automatically deployed, or you use continuous-integration because you may not have that requisite access to the files.

If you use a ‘cloud’ service like Heroku that deploys using a version-control system then this option is out of the question because the config file is not in the repository!

Private fork

Another way is to maintain a private version – or fork – of you app, storing the key information in the private repository. Again you might use JSON to keep your config, although you could keep it directy in the code:


var config = {
    db: "mongodb://localhost:27017/some-database"
};

This method means fixes and improvements go to the open-source version, and you have to manually merging them into your private version. That’s a bit of extra work, and it can create problems if you discover and fix a bug in the private fork because you’ll need to carefully branch to allow you to pull-request back into the public fork.

Having a private fork is also limited when it comes to deploying to multiple environments – like staging and production servers because you have to store configuration for both environments in the fork.

I’m using hybrid of the above for a media server called medyana. I have a private fork that hosts my podcast, Less Than Bang. It contains files.json that points to where each episode is hosted.

Unfortunately I’m also demonstrating the above problem well, because the private repo has had a number of fixes that the public code has missed out on (so far)!

It’s worth saying that this method works if your deployments are cloud-based, too.

Environment-agnostic

A good alternative is to build your app to be environment-agnostic. That means storing all configuration data in the environment – on the server – you are depoying to.

Setting environment variables is pretty simple:


export DB_URI=mongodb://localhost:27017/some-database

You app will be able to access the environment data to configure itself:


var config = {
    db: process.env.DB_URI
};

This method is fragile however, because variables set in the above way don’t persist across system restarts or even new processes.

To have them persist, set them in the .bashrc (or other shell configuration file) of the user who will be running the app (not root!):


DB_URI=mongodb://localhost:27017/some-database
TWITTER_CLIENT_ID=YOUR_CLIENT_ID
TWITTER_CLIENT_SECRET=YOUR_CLIENT_SECRET

This works for OSX and Linux, but of course, it’s different if you’re using a Windows server.

In the cloud

If you’re deploying to a cloud service like Heroku or Nodejitsu then you’ll need to use a slightly tweaked version of the environment variable method: you don’t have access to the files, you have no control over the machine your app will be run from, and deployment is done via Git!

I only have experience doing this with Heroku, so I’ll keep it specific to that service, but setting persistent environment variables on all these services is simple.

Environent management on Heroku is done with their fantastic command-line toolbelt. Amongst other things, it lets you set up environment varibales for your app:


heroku config:set TWITTER_CLIENT_ID=YOUR_CLIENT_ID TWITTER_CLIENT_SECRET=YOUR_CLIENT_SECRET

Heroku sets up some variables by default; you can view these using heroku config on its own.

Again it’s a case of bringing the variables into your app:


var config = {
    twitter: {
        id: process.env.YOUR_CLIENT_ID,
        secret: process.env.YOUR_CLIENT_SECRET
    }
};

You’ll also need to use this method if you’re using any of Heroku’s plugins, as they store their configuration data in the environment too – for example, the database providers add a database URI variable to the environment for you to use. With MongoHQ, it might look like:


config.db = process.env.MONGOHQ_URI;

I use this method with my App.net Friend Finder and a couple of other projects.

Hybrid approach: best of both

Since I deploy most of my projects using Heroku the last method is really my only option, but it’s possibly the worst for users and contributors to open-source projects. So the best thing to is to support multiple ways of configuring your app!

Setting up a chain set of fallback configuration options is reasonably simple, and if you’re using Express you might have seen code like this before.

The priority chain goes like this: arguments to the process; then environment variables; then config files and finally in-app configuration.

Here’s an example:


// Grab the config file if it's there
var configFile;
try {
    configFile = require('./config.json');
} catch (e) {
    configFile = {};
}

// Then configure!
var config = {
    port: parseInt(process.argv[2], 10) || parseInt(process.env.PORT, 10) || configFile.port || 8000,
    db: process.env.DB_URI || configFile.db || 'mongodb://localhost:27017/some-database',
    twitter: {
        id: process.env.TWITTER_CLIENT_ID || configFile.twitter.id || '',
        secret: process.env.TWITTER_CLIENT_SECRET || configFile.twitter.secret || ''
    }
};

This allows you and your contributors to easily configure the app, and modify it on the fly.

By the way, for more advanced argument handling, take a look at optimist or commander.

Summing up

Keeping things a secret while giving out all your code is no mean feat. I hope this helps you out.

I’ll be trying to use the last snippet in all future projects of mine; it makes the project easy to configure and flexible to deploy. Actually, deploying projects is something I’d like to address in a future post…

Respond

There’s an important part of painting on the web canvas often missed, and the following is a thought dump with that in mind.

Responsive web design has been called a return to the web’s roots, but I don’t think that’s true at all.

Design for the web went in the wrong direction, that’s clear, but the return to building a web that works everywhere for anyone merely brings us back to where we always should have been. It’s a baseline from which to work in the future.

However, the word responsive is, for me, the spark of a future dream. Truly responding to the user and their behaviour and context is something that I would like to explore and see explored, and the web is – perhaps uniquely – positioned to do so.

My location, my mood, the weather, my recent tweets, friend’s activity, time of day, recent behaviour… these are all context that we have ready access to but are taking little advantage of. We could do so much with them.

A button I never press, a menu I never open, a feature unused… these are contexts and behaviours that we can design for and respond to.

My point is that we know so much about a user yet we do so little with that information. A user’s device is not their context; their environment and behaviours are, and I believe we can use these to design experiences that emulate the malleable and responsive real world.

useful js: snippets

Here’s some Javascript snippets I find myself using every day. You should be good to drop them into your page, but if you’ve not familiar with a particular technique then it’s always good idea to read up on it before using it. I’ve provided links where I can.

Note: Some snippets use parts of Javascript ES5. To get this stuff in older browsers (< IE9), use the ES5 Shim.

Log arguments

Need to check the all the arguments coming into a function? No probs: use call and apply.


console.log.apply(console, [].slice.call(arguments));

Set ‘this’ in setTimeout

Want to make sure of the value of this is the same inside a setTimeout callback? Use bind.


setTimeout(function () {
  // Do yaw thang...
}.bind(this), 1000);

Call a function from setTimeout

Do you do this much?


setTimeout(function () {
  do_something_with(x, y);
}, 1000);

Try this (again with bind):


setTimeout(do_something_with.bind(this, x, y), 1000);

Filter items from an array

Need to make sure all items in an array pass certain criteria? Try filter. If you return true from the callback the item is kept, otherwise it’s scrapped.


var evens = [1,2,3,4].filter(function (val) {
  return (val % 2 === 0);
});

Operate on an array

Want to carry out an operation on every item in an array? Take a look at map.


var squares = [1,2,3,4].map(function (val) {
  return val * val;
});

Easy function defaults

You’ve got a function that can takes an optional argument, and you want to provide a default.

Use the or operator! (Also, get nerdy)


var say = function (word) {
  word = word || "Hello!";
  console.log(word);
};

say(); // logs "Hello!"
say("World!"); // logs "World!"

Further reading

The MDN Docs are great, as is Nicholas Zakas’ blog if you want to go into exra detail, and Paul Irish’s stuff.