From 16984ec97a1e3c535ffdf07d2dd33ea675586ea2 Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Tue, 21 Jun 2011 10:19:31 -0600
Subject: [PATCH] port the primary and verifier to express.  issue #21

---
 authority/server/standalone.js     |   4 +-
 primary/server/app.js              |  56 +++++++++++++
 primary/server/run.js              |  56 -------------
 primary/server/standalone.js       |  65 +++------------
 run.js                             | 122 +++++++++++++++--------------
 verifier/server/{run.js => app.js} |   7 +-
 verifier/server/standalone.js      |  65 ++-------------
 7 files changed, 145 insertions(+), 230 deletions(-)
 create mode 100644 primary/server/app.js
 delete mode 100644 primary/server/run.js
 rename verifier/server/{run.js => app.js} (95%)

diff --git a/authority/server/standalone.js b/authority/server/standalone.js
index 6623c4ae1..dd158d6aa 100644
--- a/authority/server/standalone.js
+++ b/authority/server/standalone.js
@@ -10,7 +10,7 @@ var PRIMARY_PORT = 62700;
 
 var handler = require("./app.js");
 
-var app = require('express').createServer();
+var app = express.createServer();
 
 app.use(express.logger({
     stream: fs.createWriteStream(path.join(__dirname, "server.log"))
@@ -19,7 +19,7 @@ app.use(express.logger({
 // let the specific server interact directly with the connect server to register their middleware
 if (handler.setup) handler.setup(app);
 
-// use the connect 'static' middleware for serving of static files (cache headers, HTTP range, etc)
+// use the express 'static' middleware for serving of static files (cache headers, HTTP range, etc)
 app.use(express.static(path.join(path.dirname(__dirname), "static")));
 
 app.listen(PRIMARY_PORT, PRIMARY_HOST);
diff --git a/primary/server/app.js b/primary/server/app.js
new file mode 100644
index 000000000..f44582a04
--- /dev/null
+++ b/primary/server/app.js
@@ -0,0 +1,56 @@
+const        path = require('path'),
+url = require('url'),
+wsapi = require('./wsapi.js'),
+httputils = require('./httputils.js'),
+webfinger = require('./webfinger.js'),
+sessions = require('cookie-sessions'),
+secrets = require('./secrets.js');
+
+const STATIC_DIR = path.join(path.dirname(__dirname), "static");
+
+const COOKIE_SECRET = secrets.hydrateSecret('cookie_secret', __dirname);
+
+function handler(request, response, serveFile) {
+    // dispatch!
+    var urlpath = url.parse(request.url).pathname;
+
+    if (urlpath === '/sign_in') {
+        serveFile(path.join(STATIC_DIR, "dialog", "index.html"), response);
+    } else if (/^\/wsapi\/\w+$/.test(urlpath)) {
+        try {
+            var method = path.basename(urlpath);
+            wsapi[method](request, response);
+        } catch(e) {
+            var errMsg = "oops, error executing wsapi method: " + method + " (" + e.toString() +")";
+            console.log(errMsg);
+            httputils.fourOhFour(response, errMsg);
+        }
+    } else if (/^\/users\/[^\/]+.xml$/.test(urlpath)) {
+        var identity = path.basename(urlpath).replace(/.xml$/, '').replace(/^acct:/, '');
+
+        webfinger.renderUserPage(identity, function (resultDocument) {
+            if (resultDocument === undefined) {
+                httputils.fourOhFour(response, "I don't know anything about: " + identity + "\n");
+            } else {
+                httputils.xmlResponse(response, resultDocument);
+            }
+        });
+    } else if (urlpath === "/code_update") {
+        console.log("code updated.  shutting down.");
+        process.exit();
+    } else {
+        // node.js takes care of sanitizing the request path
+        if (urlpath == "/") urlpath = "/index.html"
+        serveFile(path.join(STATIC_DIR, urlpath), response);
+    }
+};
+
+exports.setup = function(app) {
+    var week = (7 * 24 * 60 * 60 * 1000);
+    app.use(sessions({
+        secret: COOKIE_SECRET,
+        session_key: "primary_state",
+        path: '/'
+    }));
+    app.use(handler);
+};
diff --git a/primary/server/run.js b/primary/server/run.js
deleted file mode 100644
index 02e579bcb..000000000
--- a/primary/server/run.js
+++ /dev/null
@@ -1,56 +0,0 @@
-const        path = require('path'),
-              url = require('url'),
-            wsapi = require('./wsapi.js'),
-        httputils = require('./httputils.js'),
-          connect = require('connect'),
-        webfinger = require('./webfinger.js'),
-         sessions = require('cookie-sessions'),
-          secrets = require('./secrets.js');
-
-const STATIC_DIR = path.join(path.dirname(__dirname), "static");
-
-const COOKIE_SECRET = secrets.hydrateSecret('cookie_secret', __dirname);
-
-exports.handler = function(request, response, serveFile) {
-  // dispatch!
-  var urlpath = url.parse(request.url).pathname;
-
-  if (urlpath === '/sign_in') {
-    serveFile(path.join(STATIC_DIR, "dialog", "index.html"), response);
-  } else if (/^\/wsapi\/\w+$/.test(urlpath)) {
-    try {
-      var method = path.basename(urlpath);
-      wsapi[method](request, response);
-    } catch(e) {
-      var errMsg = "oops, error executing wsapi method: " + method + " (" + e.toString() +")";
-      console.log(errMsg);
-      httputils.fourOhFour(response, errMsg);
-    }
-  } else if (/^\/users\/[^\/]+.xml$/.test(urlpath)) {
-    var identity = path.basename(urlpath).replace(/.xml$/, '').replace(/^acct:/, '');
-
-    webfinger.renderUserPage(identity, function (resultDocument) {
-      if (resultDocument === undefined) {
-        httputils.fourOhFour(response, "I don't know anything about: " + identity + "\n");
-      } else {
-        httputils.xmlResponse(response, resultDocument);
-      }
-    });
-  } else if (urlpath === "/code_update") {
-      console.log("code updated.  shutting down.");
-      process.exit();
-  } else {
-    // node.js takes care of sanitizing the request path
-    if (urlpath == "/") urlpath = "/index.html"
-    serveFile(path.join(STATIC_DIR, urlpath), response);
-  }
-};
-
-exports.setup = function(server) {
-  var week = (7 * 24 * 60 * 60 * 1000);
-  server.use(sessions({
-      secret: COOKIE_SECRET,
-      session_key: "primary_state",
-      path: '/'
-  }));
-}
diff --git a/primary/server/standalone.js b/primary/server/standalone.js
index 8caedb854..7197e7c69 100644
--- a/primary/server/standalone.js
+++ b/primary/server/standalone.js
@@ -3,66 +3,23 @@ var   sys = require("sys"),
       url = require("url"),
      path = require("path"),
        fs = require("fs"),
-  connect = require("connect");
+  express = require("express");
 
 var PRIMARY_HOST = "127.0.0.1";
 var PRIMARY_PORT = 62900;
 
-var handler = require("./run.js");
+var handler = require("./app.js");
 
-function subHostNames(data) {
-    return data;
-}
+var app = express.createServer();
 
-function serveFile(filename, response) {
-  path.exists(filename, function(exists) {
-    if(!exists) {
-      response.writeHead(404, {"Content-Type": "text/plain"});
-      response.write("404 Not Found");
-      response.end();
-      return;
-    }
+app.use(express.logger({
+    stream: fs.createWriteStream(path.join(__dirname, "server.log"))
+}));
 
-    fs.readFile(filename, "binary", function(err, data) {
-      if(err) {
-        response.writeHead(500, {"Content-Type": "text/plain"});
-        response.write(err + "\n");
-        response.end();
-        return;
-      }
+// let the specific server interact directly with the connect server to register their middleware
+if (handler.setup) handler.setup(app);
 
-      var exts = {
-        ".js":   "text/javascript",
-        ".css":  "text/css",
-        ".html": "text/html",
-        ".webapp": "application/x-web-app-manifest+json",
-        ".png": "image/png",
-        ".ico": "image/x-icon"
-      };
+// use the connect 'static' middleware for serving of static files (cache headers, HTTP range, etc)
+app.use(express.static(path.join(path.dirname(__dirname), "static")));
 
-      var ext = path.extname(filename);
-      var mimeType = exts[ext] || "application/octet-stream";
-
-      data = subHostNames(data);
-
-      response.writeHead(200, {"Content-Type": mimeType});
-      response.write(data, "binary");
-      response.end();
-    });
-  });
-}
-
-var server = connect.createServer().use(connect.favicon())
-    .use(connect.logger({
-        format: ":status :method :remote-addr :response-time :url",
-        stream: fs.createWriteStream(path.join(__dirname, "server.log"))
-    }));
-
-// let the specific server interact directly with the connect server to register their middleware 
-if (handler.setup) handler.setup(server);
-
-server.use(function(req, resp, next) {
-    handler.handler(req, resp, serveFile, subHostNames);
-});
-
-server.listen(PRIMARY_PORT, PRIMARY_HOST);
+app.listen(PRIMARY_PORT, PRIMARY_HOST);
diff --git a/run.js b/run.js
index dbb48883d..0990a8d1e 100644
--- a/run.js
+++ b/run.js
@@ -5,13 +5,14 @@ var   sys = require("sys"),
       url = require("url"),
      path = require("path"),
        fs = require("fs"),
-  connect = require("connect");
+  express = require("express");
 
 var PRIMARY_HOST = "127.0.0.1";
 
-// all bound webservers stored in this lil' object
 var boundServers = [ ];
 
+// given a buffer, find and replace all production hostnames
+// with development URLs
 function subHostNames(data) {
   for (var i = 0; i < boundServers.length; i++) {
     var o = boundServers[i]
@@ -41,74 +42,77 @@ function subHostNames(data) {
   return data;
 }
 
-function createServer(obj) {
-    var server = connect.createServer().use(connect.favicon()).use(connect.logger());
-
-    // this file is a *test* harness, to make it go, we'll insert a little handler that
-    // substitutes output, changing production URLs to developement URLs.
-    server.use(function(req, resp, next) {
-        // cache the *real* functions
-        var realWrite = resp.write;
-        var realEnd = resp.end;
-        var realWriteHead = resp.writeHead;
-
-        var buf = undefined;
-        var enc = undefined;
-        var contentType = undefined;
-
-        resp.writeHead = function (sc, reason, hdrs) {
-            var h = undefined;
-            if (typeof hdrs === 'object') h = hdrs;
-            else if (typeof reason === 'object') h = reason; 
-            for (var k in h) {
-                if (k.toLowerCase() === 'content-type') {
-                    contentType = h[k];
-                    break;
-                }
+// Middleware that intercepts outbound textual responses and substitutes
+// in development hostnames
+function substitutionMiddleware(req, resp, next) {
+    // cache the *real* functions
+    var realWrite = resp.write;
+    var realEnd = resp.end;
+    var realWriteHead = resp.writeHead;
+
+    var buf = undefined;
+    var enc = undefined;
+    var contentType = undefined;
+
+    resp.writeHead = function (sc, reason, hdrs) {
+        var h = undefined;
+        if (typeof hdrs === 'object') h = hdrs;
+        else if (typeof reason === 'object') h = reason; 
+        for (var k in h) {
+            if (k.toLowerCase() === 'content-type') {
+                contentType = h[k];
+                break;
             }
-            if (!contentType) contentType = resp.getHeader('content-type');
-            if (!contentType) contentType = "application/unknown";
-            realWriteHead(sc, reason, hdrs);
-        };
-
-        resp.write = function (chunk, encoding) {
-            if (buf) buf += chunk;
-            else buf = chunk;
-            enc = encoding;
-        };
-
-        resp.end = function() {
-            if (!contentType) contentType = resp.getHeader('content-type');
-            if (contentType && (contentType === "application/javascript" ||
-                                contentType.substr(0,4) === 'text'))
-            {
-                if (buf) {
-                    var l = buf.length;
-                    buf = subHostNames(buf);
-                    if (l != buf.length) resp.setHeader('Content-Length', buf.length);
-                }
+        }
+        if (!contentType) contentType = resp.getHeader('content-type');
+        if (!contentType) contentType = "application/unknown";
+        realWriteHead(sc, reason, hdrs);
+    };
+
+    resp.write = function (chunk, encoding) {
+        if (buf) buf += chunk;
+        else buf = chunk;
+        enc = encoding;
+    };
+
+    resp.end = function() {
+        if (!contentType) contentType = resp.getHeader('content-type');
+        if (contentType && (contentType === "application/javascript" ||
+                            contentType.substr(0,4) === 'text'))
+        {
+            if (buf) {
+                var l = buf.length;
+                buf = subHostNames(buf);
+                if (l != buf.length) resp.setHeader('Content-Length', buf.length);
             }
-            if (buf && buf.length) realWrite.call(resp, buf, enc);
-            realEnd.call(resp);
         }
+        if (buf && buf.length) realWrite.call(resp, buf, enc);
+        realEnd.call(resp);
+    }
 
-        next();
-    });
+    next();
+};
+
+function createServer(obj) {
+    var app = express.createServer();
+    app.use(express.logger());
 
-    // let the specific server interact directly with the connect server to register their middleware 
-    if (obj.setup) obj.setup(server);
+    // this file is a *test* harness, to make it go, we'll insert a little handler that
+    // substitutes output, changing production URLs to developement URLs.
+    app.use(substitutionMiddleware);
 
-    // if this site has a handler, we'll run that, otherwise serve statically
-    if (obj.handler) server.use(obj.handler);
+    // let the specific server interact directly with the express server to register their middleware,
+    // routes, etc...
+    if (obj.setup) obj.setup(app);
 
     // now set up the static resource servin'
     var p = obj.path, ps = path.join(p, "static");
     try { if (fs.statSync(ps).isDirectory()) p = ps; } catch(e) { }
-    server.use(connect.static(p));
+    app.use(express.static(p));
 
     // and listen!
-    server.listen(obj.port, PRIMARY_HOST);
-    return server;
+    app.listen(obj.port, PRIMARY_HOST);
+    return app;
 };
 
 // start up webservers on ephemeral ports for each subdirectory here.
@@ -151,7 +155,7 @@ console.log("Running test servers:");
 dirs.forEach(function(dirObj) {
   if (!fs.statSync(dirObj.path).isDirectory()) return;
   // does this server have a js handler for custom request handling?
-  var handlerPath = path.join(dirObj.path, "server", "run.js");
+  var handlerPath = path.join(dirObj.path, "server", "app.js");
   var runJS = {};
   try {
     var runJSExists = false;
diff --git a/verifier/server/run.js b/verifier/server/app.js
similarity index 95%
rename from verifier/server/run.js
rename to verifier/server/app.js
index cc9e31fb8..3f1463d73 100644
--- a/verifier/server/run.js
+++ b/verifier/server/app.js
@@ -4,8 +4,7 @@ const   path = require('path'),
  idassertion = require('./idassertion.js'),
          jwt = require('./jwt.js');
 
-
-exports.handler = function(req, resp, serveFile) {
+function handler(req, resp, serveFile) {
     // dispatch!
     var parsed = url.parse(req.url, true);
 
@@ -68,3 +67,7 @@ exports.handler = function(req, resp, serveFile) {
         }
     }
 };
+
+exports.setup = function(app) {
+    app.use(handler);
+};
diff --git a/verifier/server/standalone.js b/verifier/server/standalone.js
index 3e018b438..3aebe1479 100644
--- a/verifier/server/standalone.js
+++ b/verifier/server/standalone.js
@@ -1,67 +1,18 @@
 var   sys = require("sys"),
-     http = require("http"),
-      url = require("url"),
      path = require("path"),
        fs = require("fs"),
-  connect = require("connect");
+  express = require("express");
 
 var PRIMARY_HOST = "127.0.0.1";
 var PRIMARY_PORT = 62800;
 
-var handler = require("./run.js");
+var handler = require("./app.js");
 
-function subHostNames(data) {
-    return data;
-}
+var app = express.createServer().use(express.logger({
+    stream: fs.createWriteStream(path.join(__dirname, "server.log"))
+}));
 
-function serveFile(filename, response) {
-  path.exists(filename, function(exists) {
-    if(!exists) {
-      response.writeHead(404, {"Content-Type": "text/plain"});
-      response.write("404 Not Found");
-      response.end();
-      return;
-    }
+// let the specific server interact directly with the express server to register their middleware
+if (handler.setup) handler.setup(app);
 
-    fs.readFile(filename, "binary", function(err, data) {
-      if(err) {
-        response.writeHead(500, {"Content-Type": "text/plain"});
-        response.write(err + "\n");
-        response.end();
-        return;
-      }
-
-      var exts = {
-        ".js":   "text/javascript",
-        ".css":  "text/css",
-        ".html": "text/html",
-        ".webapp": "application/x-web-app-manifest+json",
-        ".png": "image/png",
-        ".ico": "image/x-icon"
-      };
-
-      var ext = path.extname(filename);
-      var mimeType = exts[ext] || "application/octet-stream";
-
-      data = subHostNames(data);
-
-      response.writeHead(200, {"Content-Type": mimeType});
-      response.write(data, "binary");
-      response.end();
-    });
-  });
-}
-
-var server = connect.createServer().use(connect.favicon())
-    .use(connect.logger({
-        stream: fs.createWriteStream(path.join(__dirname, "server.log"))
-    }));
-
-// let the specific server interact directly with the connect server to register their middleware 
-if (handler.setup) handler.setup(server);
-
-server.use(function(req, resp, next) {
-    handler.handler(req, resp, serveFile, subHostNames);
-});
-
-server.listen(PRIMARY_PORT, PRIMARY_HOST);
+app.listen(PRIMARY_PORT, PRIMARY_HOST);
-- 
GitLab