Bogart | |
bogart | lib/bogart.js |
var EventEmitter = require('events').EventEmitter, path = require('path'), Q = require('promised-io/promise'), when = Q.when, httpMethod = { GET: "get", POST: "post", PUT: "put", DELETE: "delete" }, restMethod = { SHOW: httpMethod.GET, CREATE: httpMethod.POST, UPDATE: httpMethod.PUT, DESTROY: httpMethod.DELETE }, PATHPARAMETERREPLACEMENT = "([^\.\/\?]+)", PATH_PARAMETERS = /:([\w\d]+)/g; exports.version = [0,0,3]; var bogartEvent = exports.bogartEvent = { BEFOREADDROUTE: "beforeAddRoute", AFTERADDROUTE: "afterAddRoute" }; var Router = exports.Router = function() { var emitter = new EventEmitter(), settings = {}, k; for (k in emitter) { this[k] = emitter[k]; } this.setting = function(name, val) { if (val === undefined) { return settings[name]; }
}; }; |
|
Router.prototype.route = function(method, path, handler) { var paramNames, route, originalPath = path; if (path.constructor === String) { paramNames = path.match(PATH_PARAMETERS) || []; paramNames = paramNames.map(function(x) { return x.substring(1); });
} route = { path: path, paramNames: paramNames, handler: handler, originalPath: originalPath }; this.emit(bogartEvent.BEFOREADDROUTE, this, route); this.routes[method] = this.routes[method] || []; this.routes[method].push(route); this.emit(bogartEvent.AFTERADDROUTE, this, route); return this; }; Router.prototype.show = function(path, handler) { return this.route(restMethod.SHOW, path, handler); }; Router.prototype.create = function(path, handler) { return this.route(restMethod.CREATE, path, handler); }; Router.prototype.update = function(path, handler) { return this.route(restMethod.UPDATE, path, handler); }; Router.prototype.destroy = function(path, handler) { return this.route(restMethod.DESTROY, path, handler); }; Router.prototype.respond = function(jsgiReq) { var self = this; return when(exports.request(this, jsgiReq), function(req) { var route = self.handler(req.method, req.pathInfo), routeParams = Object.create(Object.prototype), routeParamValues = null;
}); }; Router.prototype.handler = function(verb, path) { verb = verb.toLowerCase(); var verbHandlers = this.routes[verb], route; if (verbHandlers) {
} return null; }; var Request = exports.Request = function(){}; exports.request = function(router, jsgiReq) { var search = extractSearch(jsgiReq), requestedWith = jsgiReq.headers['x-requested-with'], isxhr = !no(requestedWith), parsedBody = when(no(jsgiReq.body) ? '' : jsgiReq.body.join(), function(body) { return require('querystring').parse(body); }),
for (var k in jsgiReq) { if (k === "body") { continue; } Object.defineProperty(req, k, { value: jsgiReq[k], readonly: true, enumerable: true }); } return when(parsedBody, function(body) { Object.defineProperty(req, 'body', { value: body, readonly: true, enumerable: true });
}); }; exports.viewEngine = function(engineName, viewsPath) { var engine = require("./view").viewEngine(engineName, viewsPath || exports.maindir()+"/views"); return engine; }; exports.app = function(config, notFoundApp) { console.log("app is deprecated, please use bogart.router"); return exports.router(config, notFoundApp); }; exports.router = function(config, notFoundApp) { var defaultNotFoundApp = function(req) { var body = 'Not Found'; if (req.pathInfo) { body += ': ' + req.pathInfo; }
function bindToRouter(method) { return function() { method.apply(router, arguments); }; } config.call(router, bindToRouter(router.show), bindToRouter(router.create), bindToRouter(router.update), bindToRouter(router.destroy)); return function(req) { var resp; try { resp = router.respond(req); if (resp.status === 404 && req.pathInfo === '/routes') { var str = 'GET<br />';
}; }; exports.server = function(config) { var self = this, app; this.middleware = []; this.use = function() { this.middleware.push(Array.prototype.slice.call(arguments)); }; config.call(this); this.middleware = this.middleware.reverse(); this.middleware.forEach(function(middleware) { var args = middleware, callable = args.shift();
}); return function(req) { var resp = app(req);
}; }; exports.start = function(jsgiApp) { require("jsgi").start(jsgiApp); }; exports.text = function(txt) { return { status: 200, body: [txt], headers: { "content-type": "text", "content-length": txt.length } }; }; exports.html = function(html, opts) { opts = opts || {}; html = html || ""; return { status: opts.status || 200, body: [html], headers: { "content-type": "text/html", "content-length": html.length } }; }; exports.stream = function() { var deferred = Q.defer(), buffer = [], streamer = function(progress) { deferred.progress(progress); }; streamer.end = function() { deferred.resolve(); }; streamer.respond = function(opts) { opts = opts || {}; opts.status = opts.status || 200; opts.headers = opts.headers || { "Content-Type": "text/plain" };
}; return streamer; } exports.json = function(obj, opts) { opts = opts || {}; var str = JSON.stringify(obj); return { status: opts.status || 200, body: [str], headers: { "content-type": "application/json", "content-length": str.length } } }; exports.error = function(msg, opts) { opts = opts || {}; msg = msg || "Server Error"; return { status: opts.status || 500, body: [msg], headers: { "content-type": "text/html", "content-length": msg.length } }; }; exports.redirect = function(url) { return { status: 302, headers: { "location": url }, body: [] }; }; exports.maindir = function() { return path.dirname(require.main.id).replace("file://",""); }; function no(value) { return value === undefined || value === null; } function extractBody(jsgiReq) { return when(jsgiReq.input, function(input) { return require('querystring').parse(input); }); } function extractSearch(jsgiReq) { return require('querystring').parse(jsgiReq.queryString); } function merge(target |
|
) { var sources = Array.prototype.slice.call(arguments), k,x; sources.shift(); sources.forEach(function(source) { for (var k in source) { target[k] = source[k]; } }); return target; } |