diff --git a/packages/livedata/client_convenience.js b/packages/livedata/client_convenience.js index 207401c4d2..60f8d07a29 100644 --- a/packages/livedata/client_convenience.js +++ b/packages/livedata/client_convenience.js @@ -1,12 +1,5 @@ _.extend(Meteor, { - // XXX this isn't going to work -- when connecting to a remote - // server, the user isn't going to know to include /sockjs. need to - // add it in stream_client.. - - // Path matches sockjs 'prefix' in stream_server. We should revisit - // this once we specify the 'on the wire' aspects of livedata more - // clearly. - default_connection: Meteor.connect('/sockjs', true /* restart_on_update */), + default_connection: Meteor.connect('/', true /* restart_on_update */), refresh: function (notification) { } diff --git a/packages/livedata/livedata_connection.js b/packages/livedata/livedata_connection.js index 577acb12f6..5498aaa7ce 100644 --- a/packages/livedata/livedata_connection.js +++ b/packages/livedata/livedata_connection.js @@ -10,6 +10,7 @@ if (Meteor.is_server) { // XXX namespacing Meteor._capture_subs = null; +// @param url {String|Object} See #LivedataURL Meteor._LivedataConnection = function (url, restart_on_update) { var self = this; @@ -20,7 +21,7 @@ Meteor._LivedataConnection = function (url, restart_on_update) { // the url is used as a key for the migration data. self.url = "/debug"; } else { - self.url = url; + self.url = Meteor._LivedataConnection._toSockjsUrl(url); } self.last_session_id = null; @@ -168,6 +169,35 @@ Meteor._LivedataConnection = function (url, restart_on_update) { }); }; +_.extend(Meteor._LivedataConnection, { + // @param url {String} See #LivedataURL + // @returns {String} A URL to the sockjs endpoint, e.g. + // "http://subdomain.meteor.com/sockjs" or "/sockjs" + _toSockjsUrl: function(url) { + // XXX from Underscore.String (http://epeli.github.com/underscore.string/) + var startsWith = function(str, starts) { + return str.length >= starts.length && + str.substring(0, starts.length) === starts; + }; + var endsWith = function(str, ends) { + return str.length >= ends.length && + str.substring(str.length - ends.length) === ends; + }; + + // Prefix FQDNs but not relative URLs + if (!startsWith(url, "http://") && !startsWith(url, "/")) { + url = "http://" + url; + } + + if (endsWith(url, "/sockjs")) + return url; + else if (endsWith(url, "/")) + return url + "sockjs"; + else + return url + "/sockjs"; + } +}); + _.extend(Meteor._LivedataConnection.prototype, { // 'name' is the name of the data on the wire that should go in the // store. 'store' should be an object with methods beginUpdate, @@ -562,12 +592,18 @@ _.extend(Meteor._LivedataConnection.prototype, { return !m.callback; }); } - }); _.extend(Meteor, { - connect: function (url, _restart_on_update) { - return new Meteor._LivedataConnection(url, _restart_on_update); + // @param url {String} ##LivedataURL e.g. + // "subdomain.meteor.com" (preferred), + // "http://subdomain.meteor.com", + // "subdomain.meteor.com/sockjs" (deprecated?), + // "http://subdomain.meteor.com/sockjs" (deprecated?), + // "/", + // "/sockjs" (deprecated?) + connect: function (url, _restartOnUpdate) { + return new Meteor._LivedataConnection(url, _restartOnUpdate); }, autosubscribe: function (sub_func) { diff --git a/packages/livedata/livedata_connection_tests.js b/packages/livedata/livedata_connection_tests.js index b152ebe79c..3fc4d9cdc2 100644 --- a/packages/livedata/livedata_connection_tests.js +++ b/packages/livedata/livedata_connection_tests.js @@ -397,6 +397,31 @@ Tinytest.add("livedata stub - reconnect", function (test) { handle.stop(); }); +Tinytest.add("livedata connection - sockjs urls are computed correctly", function(test) { + var testHasSockjsUrl = function(raw, expectedSockjsUrl) { + test.equal(Meteor._LivedataConnection._toSockjsUrl(raw), expectedSockjsUrl); + }; + + testHasSockjsUrl("http://subdomain.meteor.com/sockjs", + "http://subdomain.meteor.com/sockjs"); + testHasSockjsUrl("http://subdomain.meteor.com/", + "http://subdomain.meteor.com/sockjs"); + testHasSockjsUrl("http://subdomain.meteor.com", + "http://subdomain.meteor.com/sockjs"); + testHasSockjsUrl("subdomain.meteor.com/", + "http://subdomain.meteor.com/sockjs"); + testHasSockjsUrl("subdomain.meteor.com", + "http://subdomain.meteor.com/sockjs"); + testHasSockjsUrl("/sockjs", "/sockjs"); + testHasSockjsUrl("/", "/sockjs"); + + testHasSockjsUrl("http://localhost:3000/sockjs", + "http://localhost:3000/sockjs"); + testHasSockjsUrl("http://localhost:3000/", "http://localhost:3000/sockjs"); + testHasSockjsUrl("http://localhost:3000", "http://localhost:3000/sockjs"); + testHasSockjsUrl("localhost:3000", "http://localhost:3000/sockjs"); +}); + // XXX also test: // - reconnect, with session resume. // - restart on update flag diff --git a/packages/livedata/livedata_tests.js b/packages/livedata/livedata_tests.js index 2a819900dc..23317cc574 100644 --- a/packages/livedata/livedata_tests.js +++ b/packages/livedata/livedata_tests.js @@ -238,7 +238,6 @@ testAsyncMulti("livedata - compound methods", [ } ]); - // XXX some things to test in greater detail: // staying in simulation mode // time warp diff --git a/packages/madewith/madewith.js b/packages/madewith/madewith.js index f3f6bddd67..127915bf8f 100644 --- a/packages/madewith/madewith.js +++ b/packages/madewith/madewith.js @@ -5,7 +5,7 @@ var shortname = match ? match[1] : hostname; // connect to madewith and subscribe to my app's record - var server = Meteor.connect("http://madewith.meteor.com/sockjs"); + var server = Meteor.connect("madewith.meteor.com"); var sub = server.subscribe("myApp", hostname); // minimongo collection to hold my singleton app record. diff --git a/packages/stream/stream_client.js b/packages/stream/stream_client.js index 3d7b16064d..5eb58ec397 100644 --- a/packages/stream/stream_client.js +++ b/packages/stream/stream_client.js @@ -1,3 +1,5 @@ +// @param url {String} A URL to a sockjs endpoint, e.g. +// "http://subdomain.meteor.com/sockjs" or "/sockjs" Meteor._Stream = function (url) { var self = this;