diff --git a/NEWS.md b/NEWS.md index 45446c1b..11cc4792 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,25 @@ +2015-10-19 +========== + +In order to support future clustering support, the legacy `/sioconfig` +endpoint is being deprecated. Instead, you should make a request to +`/socketconfig/.json`. The response will look similar to +these: + +```json +{"url":"https://some-website.com:8443","secure":true} +{"error":"Channel \"!@#$\" does not exist."} +``` + +The `url` key specifies the socket.io URL to connect to, and the `secure` +key indicates whether the connection is secured with TLS. If an `error` key +is present, something went wrong and the value will contain an error +message. + +For now, only one URL is returned, however in the future this may be +extended by adding an `alt` key specifying an array of acceptable URLs to +connect to. + 2015-10-04 ========== diff --git a/package.json b/package.json index 454beddc..16de6baa 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Calvin Montgomery", "name": "CyTube", "description": "Online media synchronizer and chat", - "version": "3.11.2", + "version": "3.12.0", "repository": { "url": "http://github.com/calzoneman/sync" }, diff --git a/src/configuration/ioconfig.js b/src/configuration/ioconfig.js new file mode 100644 index 00000000..9fa96a0b --- /dev/null +++ b/src/configuration/ioconfig.js @@ -0,0 +1,23 @@ +export default class IOConfiguration { + constructor(config) { + this.config = config; + } + + getSocketURL() { + return this.config.urls[0]; + } +} + +IOConfiguration.fromOldConfig = function (oldConfig) { + const config = { + urls: [] + }; + + ['ipv4-ssl', 'ipv4-nossl', 'ipv6-ssl', 'ipv6-nossl'].forEach(key => { + if (oldConfig.get('io.' + key)) { + config.urls.push(oldConfig.get('io.' + key)); + } + }); + + return new IOConfiguration(config); +}; diff --git a/src/io/cluster/nullclusterclient.js b/src/io/cluster/nullclusterclient.js new file mode 100644 index 00000000..b320e0d0 --- /dev/null +++ b/src/io/cluster/nullclusterclient.js @@ -0,0 +1,11 @@ +import Promise from 'bluebird'; + +export default class NullClusterClient { + constructor(ioConfig) { + this.ioConfig = ioConfig; + } + + getSocketURL(channel) { + return Promise.resolve(this.ioConfig.getSocketURL()); + } +} diff --git a/src/web/routes/socketconfig.js b/src/web/routes/socketconfig.js new file mode 100644 index 00000000..e45437f3 --- /dev/null +++ b/src/web/routes/socketconfig.js @@ -0,0 +1,24 @@ +import IOConfiguration from '../../configuration/ioconfig'; +import NullClusterClient from '../../io/cluster/nullclusterclient'; +import Config from '../../config'; +import CyTubeUtil from '../../utilities'; + +export default function initialize(app) { + const ioConfig = IOConfiguration.fromOldConfig(Config); + const clusterClient = new NullClusterClient(ioConfig); + + app.get('/socketconfig/:channel.json', (req, res) => { + if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) { + return res.status(400).json({ + error: `Channel "${req.params.channel}" does not exist.` + }); + } + + clusterClient.getSocketURL(req.params.channel).then(url => { + res.json({ + url, + secure: /^(https|wss)/.test(url) + }); + }); + }); +} diff --git a/src/web/webserver.js b/src/web/webserver.js index 3bd43647..a15d0d47 100644 --- a/src/web/webserver.js +++ b/src/web/webserver.js @@ -117,7 +117,8 @@ function handleIndex(req, res) { } /** - * Handles a request for the socket.io information + * Legacy socket.io configuration endpoint. This is being migrated to + * /socketconfig/.json (see ./routes/socketconfig.js) */ function handleSocketConfig(req, res) { if (/\.json$/.test(req.path)) { @@ -243,6 +244,7 @@ module.exports = { app.get("/r/:channel", handleChannel); app.get("/", handleIndex); app.get("/sioconfig(.json)?", handleSocketConfig); + require("./routes/socketconfig")(app); app.get("/useragreement", handleUserAgreement); app.get("/contact", handleContactPage); require("./auth").init(app); diff --git a/templates/channel.jade b/templates/channel.jade index 6b9a4c3b..6c8a2c6a 100644 --- a/templates/channel.jade +++ b/templates/channel.jade @@ -239,7 +239,6 @@ html(lang="en") mixin footer() script(src=sioSource) script(src="/js/data.js") - script(src="/sioconfig") script(src="/js/util.js") script(src="/js/player.js") script(src="/js/paginator.js") diff --git a/www/js/callbacks.js b/www/js/callbacks.js index 84efc394..4e409c59 100644 --- a/www/js/callbacks.js +++ b/www/js/callbacks.js @@ -1096,27 +1096,39 @@ setupCallbacks = function() { }); })(key); } -} +}; -try { +(function () { if (typeof io === "undefined") { makeAlert("Uh oh!", "It appears the connection to " + IO_URL + " " + "has failed. If this error persists, a firewall or " + "antivirus is likely blocking the connection, or the " + "server is down.", "alert-danger") .appendTo($("#announcements")); - throw false; + Callbacks.disconnect(); + return; } - var opts = { transports: ["websocket", "polling"] }; - if (IO_URL === IO_URLS["ipv4-ssl"] || IO_URL === IO_URLS["ipv6-ssl"]) { - opts.secure = true; - socket = io(IO_URL, { secure: true }); - } - socket = io(IO_URL, opts); - setupCallbacks(); -} catch (e) { - if (e) { - Callbacks.disconnect(); - } -} + $.getJSON("/socketconfig/" + CHANNEL.name + ".json") + .done(function (socketConfig) { + console.log(socketConfig); + if (socketConfig.error) { + makeAlert("Socket.io configuration returned error: " + + socketConfig.error, "alert-danger") + .appendTo($("#announcements")); + return; + } + + var opts = { + transports: ["websocket", "polling"], + secure: socketConfig.secure + }; + + socket = io(socketConfig.url, opts); + setupCallbacks(); + }).fail(function () { + makeAlert("Failed to retrieve socket.io configuration", "alert-danger") + .appendTo($("#announcements")); + Callbacks.disconnect(); + }); +})();