Browse files

(api) Router#map must be called explicitly

  • Loading branch information...
1 parent 4963776 commit 58c6f5b2309e2d5b944297bfe1a541b19fa34dd4 @cloudhead committed Feb 1, 2011
Showing with 116 additions and 112 deletions.
  1. +104 −102 lib/journey.js
  2. +2 −2 lib/journey/mock-request.js
  3. +10 −8 test/journey-test.js
View
206 lib/journey.js
@@ -37,128 +37,130 @@ for (var k in errors) { journey[k] = errors[k] }
//
// The Router
//
-journey.Router = function Router(routes, options) {
- var map = journey.map(this);
-
- map.__defineGetter__('root', function () {
- return this.get('/');
- });
-
- map.__defineGetter__('any', function () {
- return this.route(/(.*)/);
- });
+journey.Router = function Router(options) {
+ var that = this;
this.routes = [];
this.options = mixin({}, journey.options, options || {});
if (this.options.extension) {
this.options.extension = this.options.extension.replace('.', '\\.');
}
-
- // Call map() in the context of `this.map`, so `this`
- // can be used instead of the passed argument.
- routes.call(map, map);
};
journey.Router.methods = ['GET', 'PUT', 'POST', 'DELETE', 'HEAD'];
-journey.map = function (context) {
- return {
- paths: [],
- required: [],
-
- filter: function (/* variable arguments */) {
- var args = Array.prototype.slice.call(arguments),
- map = (typeof(args[args.length - 1]) === 'function') && args.pop(),
- filter = args.pop() || context.options.filter;
-
- this.required.push(filter);
- map.call(this, this);
- this.required.pop();
- },
-
- get: function (pattern, opts) { return this.route('GET', pattern, opts) },
- put: function (pattern, opts) { return this.route('PUT', pattern, opts) },
- post: function (pattern, opts) { return this.route('POST', pattern, opts) },
- del: function (pattern, opts) { return this.route('DELETE', pattern, opts) },
-
- route: function (/* variable arguments */) {
- var that = this, route,
- args = Array.prototype.slice.call(arguments).filter(function (a) { return a }),
- // Defaults
- pattern = this.paths.length ? '' : /.*/,
- ignoreCase = false,
- method = journey.Router.methods.slice(0),
- constraints = [],
- extension = context.options.extension ? '(?:' + context.options.extension + ')?' : '';
-
- Array.prototype.push.apply(constraints, this.required);
-
- args.forEach(function (arg) {
- if (journey.Router.methods.indexOf(arg) !== -1 || Array.isArray(arg)) {
- method = arg;
- } else if (typeof(arg) === "string" || arg.exec) {
- pattern = arg;
- } else {
- throw new(Error)("cannot understand route.");
- }
- });
+journey.Router.prototype = {
+ //
+ // Define the routing table
+ //
+ map: function (routes) {
+ // Calls the function in the context of this instance,
+ // so it can be used to define routes on `this`.
+ routes.call(this, this);
+ },
+ paths: [],
+ required: [],
+
+ filter: function (/* variable arguments */) {
+ var args = Array.prototype.slice.call(arguments),
+ map = (typeof(args[args.length - 1]) === 'function') && args.pop(),
+ filter = args.pop() || this.options.filter;
+
+ this.required.push(filter);
+ map.call(this, this);
+ this.required.pop();
+ },
- if (typeof(pattern) === "string") {
- pattern = escapeRe(pattern);
+ get: function (pattern, opts) { return this.route('GET', pattern, opts) },
+ put: function (pattern, opts) { return this.route('PUT', pattern, opts) },
+ post: function (pattern, opts) { return this.route('POST', pattern, opts) },
+ del: function (pattern, opts) { return this.route('DELETE', pattern, opts) },
+
+ route: function (/* variable arguments */) {
+ if (arguments[0].headers) { throw new(Error)("Router#route method renamed to 'handle'") }
+
+ var that = this, route,
+ args = Array.prototype.slice.call(arguments).filter(function (a) { return a }),
+ // Defaults
+ pattern = this.paths.length ? '' : /.*/,
+ ignoreCase = false,
+ method = journey.Router.methods.slice(0),
+ constraints = [],
+ extension = this.options.extension ? '(?:' + this.options.extension + ')?' : '';
+
+ Array.prototype.push.apply(constraints, this.required);
+
+ args.forEach(function (arg) {
+ if (journey.Router.methods.indexOf(arg) !== -1 || Array.isArray(arg)) {
+ method = arg;
+ } else if (typeof(arg) === "string" || arg.exec) {
+ pattern = arg;
} else {
- // If we're in a nested path, '/i' doesn't mean much,
- // as we concatinate strings and regexps.
- ignoreCase = this.paths.length || pattern.ignoreCase;
- pattern = pattern.source;
+ throw new(Error)("cannot understand route.");
}
- // Trim trailing and duplicate slashes and add ^$ markers
- pattern = '^' + this.paths.concat(pattern ? [pattern] : [])
- .join('/')
- .match(/^\^?(.*?)\$?$/)[1] // Strip ^ and $
- .replace(/^(\/|\\\/)(?!$)/, '') // Strip root / if pattern != '/'
- .replace(/(\/|\\\/)+/g, '/') + // Squeeze slashes
- extension;
- pattern += context.options.strictUrls ? '$' : '\\/?$'; // Add optional trailing slash if requested
- pattern = new(RegExp)(pattern, ignoreCase ? 'i' : '');
-
- context.routes.push(route = {
- pattern: pattern,
- method: Array.isArray(method) ? method : [method],
- constraints: constraints
- });
+ });
- return {
- bind: function (handler) {
- route.handler = handler;
- return route;
- },
- ensure: function (handler) {
- route.constraints.push(handler);
- return this;
- },
- filter: function (handler) {
- return this.ensure(handler || context.options.filter);
- }
- };
- },
- path: function (pattern, map) {
- this.paths.push(pattern.exec ? pattern.source
- : escapeRe(pattern));
- map.call(this, this);
- this.paths.pop();
- },
- trail: function (from, to) {
- // Logging
+ if (typeof(pattern) === "string") {
+ pattern = escapeRe(pattern);
+ } else {
+ // If we're in a nested path, '/i' doesn't mean much,
+ // as we concatinate strings and regexps.
+ ignoreCase = this.paths.length || pattern.ignoreCase;
+ pattern = pattern.source;
}
- };
-};
+ // Trim trailing and duplicate slashes and add ^$ markers
+ pattern = '^' + this.paths.concat(pattern ? [pattern] : [])
+ .join('/')
+ .match(/^\^?(.*?)\$?$/)[1] // Strip ^ and $
+ .replace(/^(\/|\\\/)(?!$)/, '') // Strip root / if pattern != '/'
+ .replace(/(\/|\\\/)+/g, '/') + // Squeeze slashes
+ extension;
+ pattern += this.options.strictUrls ? '$' : '\\/?$'; // Add optional trailing slash if requested
+ pattern = new(RegExp)(pattern, ignoreCase ? 'i' : '');
+
+ this.routes.push(route = {
+ pattern: pattern,
+ method: Array.isArray(method) ? method : [method],
+ constraints: constraints
+ });
-journey.Router.prototype = {
+ return {
+ bind: function (handler) {
+ route.handler = handler;
+ return route;
+ },
+ ensure: function (handler) {
+ route.constraints.push(handler);
+ return this;
+ },
+ filter: function (handler) {
+ return this.ensure(handler || that.options.filter);
+ }
+ };
+ },
+
+ get root() {
+ return this.get('/');
+ },
+
+ get any() {
+ return this.route(/(.*)/);
+ },
+
+ path: function (pattern, map) {
+ this.paths.push(pattern.exec ? pattern.source
+ : escapeRe(pattern));
+ map.call(this, this);
+ this.paths.pop();
+ },
+ trail: function (from, to) {
+ // Logging
+ },
// Called when the HTTP request is 'complete'
// and ready to be processed.
- route: function (request, body, callback) {
+ handle: function (request, body, callback) {
var promise = new(events.EventEmitter);
var request = Object.create(request);
var that = this;
View
4 lib/journey/mock-request.js
@@ -31,8 +31,8 @@ var mock = {
},
request: function (method, path, headers, body) {
var promise = new(events.EventEmitter);
- var result = router.route(this.mockRequest(method, path, headers),
- typeof(body) === 'object' ? JSON.stringify(body) : body);
+ var result = router.handle(this.mockRequest(method, path, headers),
+ typeof(body) === 'object' ? JSON.stringify(body) : body);
result.addListener('success', function (res) {
try {
View
18 test/journey-test.js
@@ -34,7 +34,15 @@ var resources = {
//
// Initialize the router
//
-var router = new(journey.Router)(function (map) {
+var router = new(journey.Router)({
+ filter: function (request, body, cb) {
+ return request.headers.authorized === true
+ ? cb(null)
+ : cb(new journey.NotAuthorized('Not Authorized'));
+ }
+});
+
+router.map(function (map) {
this.route('GET', 'picnic/fail').bind(resources.picnic.fail);
//map.root.bind(function (res) { res.send("Welcome to the Root") });
@@ -100,12 +108,6 @@ var router = new(journey.Router)(function (map) {
bind(function (res) { res.send(200, {"Content-Type":"text/html"}, "OK"); });
});
});
-}, {
- filter: function (request, body, cb) {
- return request.headers.authorized === true
- ? cb(null)
- : cb(new journey.NotAuthorized('Not Authorized'));
- }
});
var mock = require('lib/journey/mock-request').mock(router);
@@ -167,7 +169,7 @@ vows.describe('Journey').addBatch({
promise.emit('success', params);
}, success: undefined, constraints: []
});
- router.route(mock.mockRequest('GET', '/noparams', {}));
+ router.handle(mock.mockRequest('GET', '/noparams', {}));
return promise;
},
"should pass an empty params object": function (params) {

0 comments on commit 58c6f5b

Please sign in to comment.