Browse files

Adds a Jsgi adapter

  • Loading branch information...
1 parent 90bbc95 commit 554734ec4ef26b2834f85b13a145888c90164882 @hassox hassox committed Jan 31, 2010
Showing with 164 additions and 66 deletions.
  1. +1 −1 exmaples/node-example.js
  2. +26 −65 lib/sherpa.js
  3. +20 −0 lib/sherpa/interfaces.js
  4. +70 −0 lib/sherpa/interfaces/Jsgi.js
  5. +47 −0 lib/sherpa/interfaces/NodeJs.js
View
2 exmaples/node-example.js
@@ -28,7 +28,7 @@ http.createServer(new Sherpa.interfaces.NodeJs([
response.sendBody("I can't find what you're looking for..");
response.finish();
}]
-
+
]).listener()).listen(8000);
sys.puts("Server running at http://127.0.0.1:8000/");
View
91 lib/sherpa.js
@@ -31,10 +31,10 @@ Sherpa = {
this.finalNode = finalNode;
},
interfaces: { }
-}
+}
Sherpa.Router.prototype = {
-
+
compareRequestKeys: function(k1, k2) {
var i1 = this.requestKeys.indexOf(k1);
var i2 = this.requestKeys.indexOf(k2);
@@ -46,7 +46,7 @@ Sherpa.Router.prototype = {
return 0;
}
},
-
+
add: function(uri, options) {
var splitUri = uri.split(Sherpa.SplitRegex);
var node = this.root;
@@ -68,13 +68,13 @@ Sherpa.Router.prototype = {
}
}
}
-
+
if ((options && options.conditions) || (node.requestKey && node.destination)) {
-
+
var transplantedDestination = node.destination;
var preRequestNode = node;
node.destination = undefined;
-
+
for(var requestKeyIndex = 0; requestKeyIndex < this.requestKeys.length; requestKeyIndex++) {
var key = this.requestKeys[requestKeyIndex];
@@ -83,10 +83,10 @@ Sherpa.Router.prototype = {
if (node.requestLookup === undefined) node.requestLookup = {};
if (node.requestKey === undefined || node.requestKey == key) {
-
+
var conditionalValue = options && options.conditions[key];
node.requestKey = key;
-
+
if (typeof(conditionalValue) == 'function') {
var newNode = new Sherpa.RequestNode(node)
node.requestShortcut.push([conditionalValue, newNode])
@@ -99,7 +99,7 @@ Sherpa.Router.prototype = {
}
node = node.requestLookup[lookupValue];
}
-
+
// the current requestKey mismatches the key we have ... either
} else {
switch(this.compareRequestKeys(node.requestKey, key)) {
@@ -135,9 +135,9 @@ Sherpa.Router.prototype = {
requestKeyIndex--;
break;
}
- }
+ }
}
-
+
if (transplantedDestination) {
while(preRequestNode.requestLookup) {
if (!preRequestNode.requestLookup[null]) {
@@ -148,25 +148,25 @@ Sherpa.Router.prototype = {
preRequestNode.destination = transplantedDestination;
}
}
-
+
var route = new Sherpa.Route(this, node);
return route;
},
recognize: function(uri, request) {
var params = {};
var position = 0;
var splitUri = uri.split(Sherpa.SplitRegex);
-
+
var node = this.root;
while (uri.length > 0) {
var position = splitUri.shift().length;
var part = uri.substring(0, position);
-
+
var paramName = undefined;
var paramValue = undefined;
-
+
var matched = false;
-
+
if (node.shortcut.length != 0) {
for(var shortcutIndex in node.shortcut) {
if (match = uri.match(node.shortcut[shortcutIndex][0])) {
@@ -182,7 +182,7 @@ Sherpa.Router.prototype = {
}
}
}
-
+
if (!matched && part != '') {
if (node.lookup[part] !== undefined) {
node = node.lookup[part];
@@ -201,23 +201,23 @@ Sherpa.Router.prototype = {
if (node === undefined) {
return undefined;
}
-
+
if (paramName) {
params[paramName] = paramValue;
}
}
-
+
if (node.requestKey) {
node = this.searchRequestNodes(node, request, 0);
}
-
+
if (node === undefined || node.destination === undefined) {
return undefined;
} else {
return {'destination': node.destination, 'params': params};
}
},
-
+
searchRequestNodes: function(node, request, index) {
if (index >= this.requestKeys.length) {
return node;
@@ -236,7 +236,7 @@ Sherpa.Router.prototype = {
return node.requestShortcut[requestShortcutIndex][1];
}
}
- }
+ }
if (nextNode = node.requestLookup[request[this.requestKeys[index]]]) {
return this.searchRequestNodes(nextNode, request, index + 1);
@@ -250,12 +250,12 @@ Sherpa.Router.prototype = {
}
}
},
-
+
generate: function(name, params) {
var pathParts = [];
var route = this.routes[name];
var node = route.finalNode;
-
+
while (node && node.value) {
if (node.value.name !== undefined) {
var variableValue = params[node.value.name];
@@ -309,44 +309,5 @@ Sherpa.Node.prototype = {
}
};
-Sherpa.interfaces.NodeJs = function(routes) {
- this.routes = routes;
-}
-
-Sherpa.interfaces.NodeJs.prototype = {
- listener: function() {
- var router = new Sherpa.Router();
- var notFound = function(req, res) {
- res.sendHeader(404, {});
- res.finish();
- }
-
- for(var key in this.routes) {
- if (this.routes[key][0] == 'not found') {
- notFound = this.routes[key][1];
- } else {
- switch(this.routes[key].length) {
- case 2:
- router.add(this.routes[key][0]).to(this.routes[key][1]);
- break;
- case 3:
- router.add(this.routes[key][0], this.routes[key][1]).to(this.routes[key][2]);
- break;
- default:
- throw("must be 2 or 3");
- }
- }
- }
-
- return function(httpRequest, httpResponse) {
- var response = router.recognize(httpRequest.uri.path, httpRequest);
- if (response) {
- httpRequest.sherpaResponse = response;
- response.destination(httpRequest, httpResponse);
- } else {
- notFound(httpRequest, httpResponse);
- }
- }
-
- }
-}
+// load the interfaces
+require('./sherpa/interfaces')
View
20 lib/sherpa/interfaces.js
@@ -0,0 +1,20 @@
+var sys = require('sys');
+var sint = Sherpa.interfaces = Sherpa.interfaces || {};
+var interfaces = {};
+
+["NodeJs", "Jsgi"].forEach(function(interface){
+ sint.__defineGetter__(interface, function(){
+ return loadInterfaceFor(interface)
+ });
+});
+
+function loadInterfaceFor(type){
+ if(!interfaces[type]){
+ interfaces[type] = require("./interfaces/" + type)[type];
+ }
+ return interfaces[type];
+}
+
+
+
+
View
70 lib/sherpa/interfaces/Jsgi.js
@@ -0,0 +1,70 @@
+exports.Jsgi = Jsgi;
+
+/* An interface for jsgi for the Sherpa Router.
+ *
+ * The sherpa instance is made available as the "sherpa" attribute on the function.
+ *
+ * @params app - The application to use as the defualt application. I.e. if no matches are found, this application will be used.
+ * @params routerOrFunction - Can either be a Sherpa.Router, or a function that will receive the router as an argument. Use this to set your routes.
+ *
+ * @example
+ * // Using a function to configure routes
+ *
+ * new Sherpa.interfaces.jsgi(myApp, function(router){
+ * router.add("/foo" ).to(aValidJsgiAppCalledFoo())
+ * router.add("/users/:username").to(userJsgiApp())
+ * });
+ *
+ * @example
+ * // Using a pre-built sherpa for the router
+ * // This application will fall back to a 404 "NOT FOUND" application
+ *
+ * var router = new Sherpa.Router();
+ *
+ * router.add("/foo" ).to(aValidJsgiAppCalledFoo());
+ * router.add("/users/:username").to(userJsgiApp);
+ *
+ * var app = new Sherpa.interfaces.jsgi(null, router);
+ *
+ * app.sherpa // the actual sherpa router instance
+ */
+function Jsgi(app, routerOrFunction){
+ var router;
+ if(!app) app = notFound;
+
+ // TODO: Work out a better way of checking if it's an instance of Sherpa.Router
+ if(routerOrFunction instanceof Sherpa.Router){
+ router = routerOrFunction;
+ } else if( routerOrFunction instanceof Function ){
+ router = new Sherpa.Router;
+ routerOrFunction(router);
+ }
+
+ function jsgiSherpa(request){
+ var result = router.recognize(request.url, request);
+ if(result){
+ request.env.router = result;
+ return result.destination instanceof Function ?
+ result.destination(request) : app(request);
+ } else {
+ return app(request);
+ }
+ }
+ jsgiSherpa.router = router;
+ return jsgiSherpa;
+}
+
+function notFound(request){
+ var
+ body = new request.jsgi.stream,
+ msg = "NOT FOUND";
+ body.write(msg);
+ body.close();
+ return {
+ status : 404,
+ headers : {"content-type" : "text/plain", "content-length" : msg.length},
+ 'body' : body
+ }
+}
+
+
View
47 lib/sherpa/interfaces/NodeJs.js
@@ -0,0 +1,47 @@
+exports.NodeJs = NodeJs;
+
+var url = require('url');
+
+function NodeJs(routes) {
+ this.routes = routes;
+}
+
+NodeJs.prototype = {
+ listener: function() {
+ var router = new Sherpa.Router();
+ var notFound = function(req, res) {
+ res.sendHeader(404, {});
+ res.finish();
+ }
+
+ for(var key in this.routes) {
+ if (this.routes[key][0] == 'not found') {
+ notFound = this.routes[key][1];
+ } else {
+ switch(this.routes[key].length) {
+ case 2:
+ router.add(this.routes[key][0]).to(this.routes[key][1]);
+ break;
+ case 3:
+ router.add(this.routes[key][0], this.routes[key][1]).to(this.routes[key][2]);
+ break;
+ default:
+ throw("must be 2 or 3");
+ }
+ }
+ }
+
+ return function(httpRequest, httpResponse) {
+ var requestUrl = url.parse(httpRequest.url)
+ var response = router.recognize(requestUrl.pathname, httpRequest);
+ if (response) {
+ httpRequest.sherpaResponse = response;
+ response.destination(httpRequest, httpResponse);
+ } else {
+ notFound(httpRequest, httpResponse);
+ }
+ }
+
+ }
+}
+

0 comments on commit 554734e

Please sign in to comment.