You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ripple.apache.org by gt...@apache.org on 2013/03/11 16:11:05 UTC

[18/50] [abbrv] git commit: Emulate a remote (proxied) website using the hosted build target.

Emulate a remote (proxied) website using the hosted build target.

You can now (in addition to the `--path` option) enable over a remote
website (app). Ex:

    ripple emulate --remote http://foo.com

Then navigate to (what is logged):

    http://localhost:PORT

Which should load the remote site as it should be.

To enable Ripple's client UI around it, you can add the enableripple
query param:

    http://localhost:PORT?enableripple=true

Note: This is NOT perfect. Some tweaks will be needed.


Project: http://git-wip-us.apache.org/repos/asf/incubator-ripple/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ripple/commit/8a9bf628
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ripple/tree/8a9bf628
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ripple/diff/8a9bf628

Branch: refs/heads/master
Commit: 8a9bf628a611cd10aa16a511744d7854e00e08fe
Parents: 70d5836
Author: Brent Lintner <br...@gmail.com>
Authored: Fri Dec 14 02:33:51 2012 -0500
Committer: Brent Lintner <br...@gmail.com>
Committed: Wed Feb 6 16:46:27 2013 -0500

----------------------------------------------------------------------
 README.md                    |    4 +
 build/targets/hosted.js      |    5 +-
 doc/cli/emulate.md           |    5 +-
 lib/server/emulate.js        |   23 +++---
 lib/server/emulate/hosted.js |  141 ++++++++++++++++++++++++++++++++-----
 package.json                 |    2 +-
 6 files changed, 146 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 537c55a..deac0ee 100644
--- a/README.md
+++ b/README.md
@@ -59,6 +59,10 @@ Ex (using the NPM package):
 
     ripple emulate --path to/my/app
 
+    # or
+
+    ripple emulate --remote http://remote-site.com
+
 Then navigating to (your app's html file):
 
     http://localhost:PORT/index.html?enableripple=true

http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/build/targets/hosted.js
----------------------------------------------------------------------
diff --git a/build/targets/hosted.js b/build/targets/hosted.js
index fed568b..71d15e5 100644
--- a/build/targets/hosted.js
+++ b/build/targets/hosted.js
@@ -32,12 +32,11 @@ module.exports = function (src, baton) {
         var css = path.join(_c.ASSETS + "client", "ripple.css"),
             cssDeploy = path.join(PKG_BUILD_DIR, "ripple.css"),
             jsDeploy = path.join(PKG_BUILD_DIR, "ripple.js"),
-            htmlDeploy = path.join(PKG_BUILD_DIR, "ripple.html"),
+            htmlDeploy = path.join(PKG_BUILD_DIR, "index.html"),
             html = src.html.replace(/#OVERLAY_VIEWS#/g, src.overlays)
                           .replace(/#PANEL_VIEWS#/g, src.panels)
                           .replace(/#DIALOG_VIEWS#/g, src.dialogs)
-                          .replace(/#URL_PREFIX#/g, "/")
-                          .replace(_c.SPACES_AND_TABS, " ");
+                          .replace(/#URL_PREFIX#/g, "/ripple/assets/");
 
         fs.writeFileSync(cssDeploy, fs.readFileSync(css, "utf-8") + src.skins);
 

http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/doc/cli/emulate.md
----------------------------------------------------------------------
diff --git a/doc/cli/emulate.md b/doc/cli/emulate.md
index a4ab0ec..fd86743 100644
--- a/doc/cli/emulate.md
+++ b/doc/cli/emulate.md
@@ -1,6 +1,6 @@
 # Synopsis
 
-    ripple emulate [--port xxxx] [--path xxxx] [--route xxxx]
+    ripple emulate [--port xxxx] [--path xxxx] [--remote xxxx] [--route xxxx]
 
 # Description
 
@@ -12,8 +12,11 @@
 
 * --port    the port to host the application on (defaults to 4400)
 * --path    app path to statically serve for testing (if omitted, the current working directory will be used)
+* --remote  instead of a (local) --path, you can specify a remote website to load (via proxy) and emulate
 * --route   specify the URL path on which ripple services will run (defaults to '/ripple') example: http://localhost:1234/ripple/xhr_proxy
 
 # Example usage
 
     ripple emulate --port 1234 --path path/to/my/application/root
+
+    ripple emulate --remote http://google.com

http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/lib/server/emulate.js
----------------------------------------------------------------------
diff --git a/lib/server/emulate.js b/lib/server/emulate.js
index c504e77..3bd4b13 100644
--- a/lib/server/emulate.js
+++ b/lib/server/emulate.js
@@ -35,20 +35,21 @@ module.exports = {
 
         app = proxy.start({route: options.route}, app);
 
-        // TODO: Only inject via a cmd line option?
-        //    i.e. I may be using extension, and just want static server with proxy
+        // TODO: How to make into a dynamic route (using options.route)? (set at build time right now)
+        app.use("/ripple/assets", express.static(__dirname + "/../../pkg/hosted"));
         app.use(hosted.inject(options));
-        // TODO: UI assets can clash with hosted app's dir/file names (ex: themes)
-        app.use(express.static(__dirname + "/../../pkg/hosted"));
 
-        app.use(express.static(options.path));
-
-        app.use(options.route + "/enable/", express.static(__dirname + "/../../assets/server"));
+        if (!options.remote) {
+            app.use(express.static(options.path));
+        }
 
-        console.log();
-        console.log("INFO:".green + " Load the URL below (in Chrome) to auto-enable Ripple.");
-        console.log("      " + ("http://localhost:" + app._port + options.route + "/enable/").cyan);
-        console.log();
+// TODO: This should just talk about how to enable ripple via query params
+//        app.use(options.route + "/enable/", express.static(__dirname + "/../../assets/server"));
+//
+//        console.log();
+//        console.log("INFO:".green + " Load the URL below (in Chrome) to auto-enable Ripple.");
+//        console.log("      " + ("http://localhost:" + app._port + options.route + "/enable/").cyan);
+//        console.log();
 
         return app;
     }

http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/lib/server/emulate/hosted.js
----------------------------------------------------------------------
diff --git a/lib/server/emulate/hosted.js b/lib/server/emulate/hosted.js
index 77ecba8..9fdfe3e 100644
--- a/lib/server/emulate/hosted.js
+++ b/lib/server/emulate/hosted.js
@@ -15,9 +15,10 @@
  */
 var fs = require('fs'),
     path = require('path'),
+    request = require('request'),
+    url = require('url'),
 
-    // TODO: this head regex should match anything
-    HEAD_TAG = /<head>/,
+    HEAD_TAG = /<\s*head\s*>/,
 
     HOSTED_PKG_DIR = path.join(__dirname, "..", "..", "..", "pkg", "hosted"),
 
@@ -25,29 +26,133 @@ var fs = require('fs'),
                                 'window.top.ripple("bootstrap").inject(window, document);' +
                             '}';
 
-module.exports = {
-    inject: function (opts) {
-        return function (req, res, next) {
-            if (req.query.enableripple) {
-                res.sendfile(path.join(HOSTED_PKG_DIR, "ripple.html"));
-            } else if (req.path.match(/^\/$/) || req.path.match(/\.html/)) {
-                file = path.join(opts.path, (req.path.match(/\/$/) ?
-                                "index.html" : req.path));
+// TODO: Put this and xhr_proxy into common file (epic DRY..)?
+function proxyRemote(opts, req, res) {
+    var proxyReqData,
+        proxyReqHeaders,
+        proxyReq,
+        parsedURL = url.parse(opts.url),
+
+        // TODO: There should be a better way to inject on files...
+        shouldInjectInto = req.path.match(/^\/$/) || req.path.match(/\.html/);
+
+    console.log("INFO:".green + " Remote proxy: Retrieve -> " + opts.url);
+
+    proxyReqHeaders = Object.keys(req.headers).reduce(function (headers, key) {
+        if (key !== "origin") {
+            headers[key] = req.headers[key];
+        }
+        return headers;
+    }, {});
+
+    proxyReqHeaders["host"] = parsedURL.host;
 
-                fs.readFile(file, "utf-8", function (err, data) {
-                    if (err) { throw new Error(err); }
+    if (opts.userAgent) {
+        proxyReqHeaders["user-agent"] = opts.userAgent;
+    }
+
+    // HACK: Makes https://google.com crash (issue with node? request? us?)
+    delete proxyReqHeaders["accept-encoding"];
+
+    proxyReqData = {
+        url: parsedURL,
+        method: req.method,
+        headers: proxyReqHeaders
+    };
 
-                    var doc = data.replace(HEAD_TAG,
+    if (Object.keys(req.body).length > 0) {
+        if (req.get("content-type") === "application/json") {
+            proxyReqData.body = JSON.stringify(req.body);
+        } else {
+            proxyReqData.form = req.body;
+        }
+    }
+
+    // Attempt to catch any synchronously thrown exceptions
+    try {
+        proxyReq = request(proxyReqData, function (error, response, body) {
+            if (error) {
+                console.log("ERROR:".red + " Remote proxying failed with:", error);
+                res.send(500, error);
+            } else if (shouldInjectInto) {
+                if (body) {
+                    // pretty sure this callback can be called multiple times (not just when complete)
+                    body = body.replace(HEAD_TAG,
                               '<head>' +
                                 '<script>' +
                                     BOOTSTRAP_FROM_IFRAME +
                                 '</script>');
 
-                    res.send(doc);
-                });
-            } else {
-                next();
+                    // TODO: Why only need to set new content-length here (and not for localInjection)?
+                    response.headers['content-length'] = body.length;
+
+                    res.status(response.statusCode);
+                    res.set(response.headers);
+                    res.send(body);
+                }
             }
-        };
+        });
+
+        // TODO: Pipe is awesome, but can't modify body (?)
+        if (!shouldInjectInto) {
+            proxyReq.pipe(res);
+        }
+    } catch (e) {
+        res.send(500, e.toString());
+    }
+}
+
+function remoteInjection(opts) {
+    return function (req, res, next) {
+        if (req.query.enableripple) {
+            res.sendfile(path.join(HOSTED_PKG_DIR, "index.html"));
+        } else if (!req.originalUrl.match(/\/ripple\/assets/)) {
+            proxyRemote({
+                url: opts.remote + req.url,
+                userAgent: opts.userAgent
+            }, req, res);
+        } else {
+            next();
+        }
+    };
+}
+
+function localInjection(opts) {
+    return function (req, res, next) {
+        var file;
+
+        // TODO: DRY (see proxyRemote function)
+        if (req.query.enableripple) {
+            res.sendfile(path.join(HOSTED_PKG_DIR, "index.html"));
+        } else if (req.path.match(/^\/$/) || req.path.match(/\.html/)) {
+            file = opts.path + (req.path.match(/\/$/) ?
+                            req.path + "/index.html" : req.path);
+
+            fs.readFile(file, "utf-8", function (err, data) {
+                if (err) { throw new Error(err); }
+
+                var doc = data.replace(HEAD_TAG,
+                          '<head>' +
+                            '<script>' +
+                                BOOTSTRAP_FROM_IFRAME +
+                            '</script>');
+
+                res.send(doc);
+            });
+        } else {
+            next();
+        }
+    };
+}
+
+module.exports = {
+    inject: function (opts) {
+        if (opts.remote) {
+            console.log("INFO:".green + " Remote proxy set to: " + opts.remote);
+        }
+
+        return opts.remote ?
+            remoteInjection(opts) :
+            localInjection(opts);
     }
 };

http://git-wip-us.apache.org/repos/asf/incubator-ripple/blob/8a9bf628/package.json
----------------------------------------------------------------------
diff --git a/package.json b/package.json
index f5b2366..28ed8d3 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
   "dependencies": {
     "express": "3.0.0rc5",
     "connect-xcors": "0.5.2",
-    "request": "2.11.4",
+    "request": "2.12.0",
     "colors" : "0.6.0-1"
   },
   "devDependencies": {