Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ for *JSON* consuming clients.
synopsis
--------

```javascript
var journey = require('journey');

//
Expand Down Expand Up @@ -47,45 +48,57 @@ synopsis
});
});
}).listen(8080);
```

installation
------------

```shell
$ npm install journey
```

API
---

You create a router with the `journey.Router` constructor:

```javascript
var router = new(journey.Router);
```

You define some routes, with bound functions:

```javascript
router.get('/hello').bind(function (req, res) { res.send('Hi there!') });
router.put('/candles').bind(function (req, res) { ... });
```

*Note that you may also use the `map` function to define routes.*

The `router` object exposes a `handle` method, which takes three arguments:
an `http.ServerRequest` instance, a body, and a callback, as such:

```javascript
function route(request, body, callback)
```

and asynchronously calls the callback with an object containing the response
headers, status and body, on the first matching route:

```javascript
{ status: 200,
headers: {"Content-Type":"application/json"},
body: '{"journey":"Welcome"}'
}
```

Note that the response body will either be JSON data, or empty.

### Routes #

Here are a couple of example routes:

```javascript
// route // matching request
router.get('/users') // GET /users
router.post('/users') // POST /users
Expand All @@ -103,43 +116,54 @@ Here are a couple of example routes:
return req.body.length > 0;
}
});
```

Any of these routes can be bound to a function or object which responds
to the `apply` method. We use `bind` for that:

```javascript
router.get('/hello').bind(function (req, res) {});
```

If there is a match, the bound function is called, and passed the `response` object,
as first argument. Calling the `send` method on this object will trigger the callback,
passing the response to it:

```javascript
router.get('/hello').bind(function (req, res) {
res.send(200, {}, {hello: "world"});
});
```

The send method is pretty flexible, here are a couple of examples:

```javascript
// status, headers, body
res.send(404); // 404 {} ''
res.send("Welcome"); // 200 {} '{"journey":"Welcome"}'
res.send({hello:"world"}); // 200 {} '{"hello":"world"}'

res.send(200, {"Server":"HAL/1.0"}, ["bob"]);
```

As you can see, the body is automatically converted to JSON, and if a string is passed,
it acts as a message from `journey`. To send a raw string back, you can use the `sendBody` method:

```javascript
res.sendBody(JSON.stringify({hello:"world"}));
```

This will bypass JSON conversion.

### URL parameters #

Consider a request such as `GET /users?limit=5`, I can get the url params like this:

```javascript
router.get('/users').bind(function (req, res, params) {
params.limit; // 5
});
```

How about a `POST` request, with form data, or JSON? Same thing, journey will parse the data,
and pass it as the last argument to the bound function.
Expand All @@ -153,12 +177,14 @@ say we have a request like `GET /trolls/42`, and the following route:

Here's how we can access the captures:

```javascript
router.get(/^([a-z]+)\/([0-9]+)$/).bind(function (req, res, resource, id, params) {
res; // response object
resource; // "trolls"
id; // 42
params; // {}
});
```

### Summary #

Expand All @@ -171,6 +197,7 @@ A bound function has the following template:
Sometimes it's useful to have a bunch of routes under a single namespace, that's what the `path` function does.
Consider the following path and unbound routes:

```javascript
router.path('/domain', function () {
this.get(); // match 'GET /domain'
this.root; // match 'GET /domain/'
Expand All @@ -181,11 +208,13 @@ Consider the following path and unbound routes:
this.get(); // match 'GET /domain/users'
});
})
```

### Filters #

Often it's convenient to disallow certain requests based on predefined criteria. A great example of this is Authorization:

```javascript
function authorize (request, body, cb) {
return request.headers.authorized === true
? cb(null)
Expand All @@ -197,17 +226,21 @@ Often it's convenient to disallow certain requests based on predefined criteria.
? cb(null)
: cb(new journey.NotAuthorized('Not Admin'));
}
```

Journey exposes this in three separate location through the `filter` API:

#### Set a global filter

```javascript
var router = new(journey.Router)({ filter: authorize });
```

*Note: This filter will not actually be enforced until you use the APIs exposed in (2) and (3)*

#### Set a scoped filter in your route function

```javascript
var router = new(journey.Router)({ filter: authorize });

router.map(function () {
Expand All @@ -223,9 +256,11 @@ Journey exposes this in three separate location through the `filter` API:
//
});
});
```

#### Set a filter on an individual route

```javascript
var router = new(journey.Router)({ filter: authorize });

router.map(function () {
Expand All @@ -241,16 +276,19 @@ Journey exposes this in three separate location through the `filter` API:
//
});
});
```

### Accessing the request object #

From a bound function, you can access the request object with `this.request`, consider
a request such as `POST /articles`, and a route:

```javascript
router.route('/articles').bind(function (req, res) {
this.request.method; // "POST"
res.send("Thanks for your " + this.request.method + " request.");
});
```

license
-------
Expand Down