Permalink
Browse files

Initial commit of actual source ;-)

  • Loading branch information...
1 parent 246a502 commit 7b79bb8eb1b5c075091a8a7f4da2b99e1fe92ce2 @knowlecules committed May 7, 2012
Showing with 249 additions and 0 deletions.
  1. +76 −0 examples/client.js
  2. +43 −0 examples/server.js
  3. +130 −0 lib/rapid-rest.js
View
@@ -0,0 +1,76 @@
+var http = require('http');
+
+var MAX_ITERATIONS = 1;
+var port =8004;
+
+var surveys = [
+ {name:"Survey1", user: "UserA", answers:{"Q1":1,"Q2":2,"Q3":2,"Q4":2,"Q5":2,"Q6":2,"Q7":2,"Q8":2,"Q9":2,"Q10":2,"Q11":2,"Q12":2,"Q13":2,"Q14":2}},
+ {name:"Survey2", user: "UserB", answers:{"Q1":1,"Q2":2,"Q3":2,"Q4":2,"Q5":2,"Q6":2,"Q7":2,"Q8":2}},
+ {name:"Survey3", user: "UserC", answers:{"Q1":1,"Q2":2,"Q3":2,"Q4":2,"Q5":2,"Q6":2,"Q7":2,"Q8":2,"Q9":2,"Q10":2}}
+]
+
+var options = {
+ host: 'localhost',
+ port: port,
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ }};
+
+// calling here
+var collection = "here";
+var survey = surveys[0];
+options.path = '/' +collection+ '/'+ survey.name + '/' + survey.user;
+
+var req = http.request(options, function(res) {
+ if(res.statusCode != 201){
+ console.log('STATUS: ' + res.statusCode);
+ console.log('HEADERS: ' + JSON.stringify(res.headers));
+ }else{
+ console.log('SUCCESS');
+ }
+ res.setEncoding('utf8');
+
+ res.on('data', function (chunk) {
+ console.log('BODY: ' + chunk);
+ });
+});
+
+
+req.on('error', function(e) {
+ console.log('problem with request: ' + e.message);
+});
+
+// write data to request body
+req.write(JSON.stringify(survey.answers));
+req.end();
+
+// calling there
+var collection = "there";
+var survey = surveys[1];
+options.path = '/' +collection+ '/'+ survey.name + '/';
+
+var req = http.request(options, function(res) {
+ if(res.statusCode != 201){
+ console.log('STATUS: ' + res.statusCode);
+ console.log('HEADERS: ' + JSON.stringify(res.headers));
+ }else{
+ console.log('SUCCESS: ' + JSON.stringify(res.headers));
+ }
+ res.setEncoding('utf8');
+
+ res.on('data', function (chunk) {
+ console.log('BODY: ' + chunk);
+ });
+});
+
+
+req.on('error', function(e) {
+ console.log('problem with request: ' + e.message);
+});
+
+// write data to request body
+req.write(JSON.stringify(survey.answers));
+req.end();
+
+console.log(" interacting on port:" + port);
View
@@ -0,0 +1,43 @@
+var routes = require("../lib/rapid-rest")();
+var port = 8004;
+
+/* Accepts a POST at URL matching /here/?A?/?B?
+params.here_name = ?A?
+params.user = ?B?
+*/
+routes('/here/:here_name/:user')
+ ('post', function(req, res, params, jsonData){
+ here(req, res, params, jsonData);
+ });
+
+
+/* Accepts a POST at URL matching /here/?A?/?B?
+params.over_name = ?A?
+*/
+routes('/there/:over_name')
+ ('post', function(req, res, params, jsonData){
+ there(req, res, params, jsonData);
+ });
+routes.listen(port);
+
+var interval;
+function here(req, res, params, bodyContents) {
+ var msg = "got 'here'";
+ console.log(msg);
+ console.dir(bodyContents);
+ console.dir(params);
+
+ res.writeHead(201, '', {'Content-Type': 'text/html'});
+ res.end(msg);
+};
+
+function there(req, res, params, bodyContents) {
+ var msg = "went 'there'";
+ console.log(msg);
+ console.dir(bodyContents);
+ console.dir(params);
+
+ res.writeHead(201,'' , {'Content-Type': 'text/html'});
+ res.end(msg);
+};
+console.log(" listening on port:" + port);
View
@@ -0,0 +1,130 @@
+var http = require('http');
+
+module.exports = function() {
+ var rest = function(route) {
+ return rest.handlers(rest.router.add(route));
+ };
+ rest.matchDefs = {};
+ rest.respond = function(res, code, headers, data) {
+ if (code && headers && !data) {
+ data = headers;
+ headers = {};
+ } else if (code && !headers && !data) {
+ data = code;
+ code = 200;
+ headers = {};
+ }
+
+ if (typeof data === 'object') {
+ data = JSON.stringify(data);
+ headers['Content-type'] = headers['Content-type'] || 'application/json';
+ }
+
+ if (!headers['Content-length'] && typeof data === 'string') {
+ headers['Content-length'] = data.length;
+ }
+
+ // TODO: streams, json, html (look for <)
+ res.writeHead(code, headers);
+ res.end(data);
+ }
+ rest.handlers = function(route){
+ route.methods = route.methods || {};
+
+ route.methods.options = route.methods.options || function(ctx) {
+ var methods = Object.keys(route.methods).filter(function(key) {
+ return key !== 'options';
+ });
+
+ ctx.respond(200, methods);
+ };
+
+ route.method = function(rawVerb, accept, fn) {
+
+ if (rawVerb && accept && !fn) {
+ fn = accept;
+ accept = null
+ }
+
+ var verb = rawVerb.toLowerCase();
+ if (verb[0] != 'p') {
+ route.methods[verb] = function(req, res, segments) {
+ fn(req, res, segments);
+ };
+ }else{
+ route.methods[verb] = function(req, res, segments) {
+ var body = '';
+ req.on('data', function (data) {
+ body += data;
+ if (body.length > 1e6) {
+ // FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
+ req.connection.destroy();
+ }
+ });
+ req.on('end', function () {
+ //TODO: Switch contentType
+
+ var data = body;// JSON.parse(body);
+ fn(req, res, segments, data);
+ });
+ }
+ }
+ return route.method;
+ };
+ return route.method;
+ };
+
+ rest.router = (function() {
+ var routes = {};
+
+ return {
+ add : function(url) {
+ var location = routes;
+ var urlMatch = url.replace(/[\-[\]\{\}\(\)\*\+\?\.,\/\\\^\$\|#\s]/g, "\\$&").replace(/(:[^(\\/)]+)/g,"([^/]*)");
+ var patternRE = new RegExp(urlMatch);
+ var paramKeys = (url.indexOf("/:")) ? url.replace(/(\/[^:][^\/]+)/g, '').substr(2).split("/:") :[];
+ location[urlMatch] = rest.handlers({});
+ rest.matchDefs[urlMatch] = {re:patternRE, paramKeys:paramKeys};
+ return location[urlMatch];
+ },
+ handle : function(req, res) {
+ // Handle options
+
+ var method = req.method.toLowerCase();
+
+ var location = routes;
+ var paramKeys;
+ var params={};
+ for (var pattern in rest.matchDefs) {
+ var urlParams = req.url.match(rest.matchDefs[pattern].re);
+ if ( urlParams != null){
+ // Align variables in the URL with the REST definition
+ var paramKeys = rest.matchDefs[pattern].paramKeys;
+ for(var ikey=0; ikey < paramKeys.length; ikey++) {
+ params[paramKeys[ikey]] = urlParams[ikey + 1];
+ }
+ location = routes[pattern];
+ break;
+ }
+ }
+
+ if (!location.methods || !location.methods[method]) {
+ return rest.respond(res, 501, {'Content-type' : 'text/plain'}, 'Not Implemented');
+ }
+
+ location.methods[method](req, res, params);
+
+ },
+
+ respond : function(code, headers, data) {
+ rest.respond(res,code, headers, data);
+ }
+ }
+ })()
+
+ rest.listen = function(host, port, cb) {
+ http.createServer(rest.router.handle).listen(host, port, cb);
+ };
+
+ return rest;
+};

0 comments on commit 7b79bb8

Please sign in to comment.