Merge pull request #522 from calzoneman/sioconfig-migration
Migrate socket.io configuration to new API
This commit is contained in:
commit
535b1d5d3a
8
NEWS.md
8
NEWS.md
|
@ -1,3 +1,11 @@
|
|||
2015-10-25
|
||||
==========
|
||||
|
||||
In order to support future clustering support, the legacy `/sioconfig`
|
||||
endpoint is being deprecated. Instead, you should make a request to
|
||||
`/socketconfig/<channel name>.json`. See [the
|
||||
documentation](docs/socketconfig.md) for more information.
|
||||
|
||||
2015-10-04
|
||||
==========
|
||||
|
||||
|
|
57
docs/socketconfig.md
Normal file
57
docs/socketconfig.md
Normal file
|
@ -0,0 +1,57 @@
|
|||
Socket.IO Client Configuration
|
||||
==============================
|
||||
|
||||
As of 2015-10-25, the legacy `/sioconfig` JavaScript for retrieving connection
|
||||
information is being deprecated in favor of a new API. The purpose of this
|
||||
change is to allow partitioning channels across multiple servers in order to
|
||||
better handle increasing traffic.
|
||||
|
||||
To get the socket.io configuration for the server hosting a particular channel,
|
||||
make a `GET` request to `/socketconfig/<channel name>.json`. The response will
|
||||
be a JSON object containing a list of acceptable servers to connect to, or an
|
||||
error message.
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
GET /socketconfig/test.json
|
||||
200 OK
|
||||
|
||||
{
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://localhost:8443",
|
||||
"secure": true
|
||||
},
|
||||
{
|
||||
"url": "http://localhost:1337",
|
||||
"secure": false
|
||||
},
|
||||
{
|
||||
"url": "https://local6:8443",
|
||||
"secure": true,
|
||||
"ipv6": true
|
||||
},
|
||||
{
|
||||
"url": "http://local6:1337",
|
||||
"secure": false,
|
||||
"ipv6": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
GET /socketconfig/$invalid$.json
|
||||
404 Not Found
|
||||
|
||||
{
|
||||
"error": "Channel \"$invalid$\" does not exist."
|
||||
}
|
||||
```
|
||||
|
||||
Each entry in the `servers` array has `"secure":true` if the connection is
|
||||
secured with TLS, otherwise it it is false. An entry with `"ipv6":true`
|
||||
indicates that the server is listening on the IPv6 protocol.
|
||||
|
||||
You can pick any URL to connect socket.io to in order to join the specified
|
||||
channel. I recommend picking one with `"secure":true`, only choosing an
|
||||
insecure connection if implementing a TLS connection is infeasible.
|
|
@ -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"
|
||||
},
|
||||
|
|
47
src/configuration/ioconfig.js
Normal file
47
src/configuration/ioconfig.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
export default class IOConfiguration {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
getSocketEndpoints() {
|
||||
return this.config.endpoints.slice();
|
||||
}
|
||||
}
|
||||
|
||||
IOConfiguration.fromOldConfig = function (oldConfig) {
|
||||
const config = {
|
||||
endpoints: []
|
||||
};
|
||||
|
||||
if (oldConfig.get('io.ipv4-ssl')) {
|
||||
config.endpoints.push({
|
||||
url: oldConfig.get('io.ipv4-ssl'),
|
||||
secure: true
|
||||
});
|
||||
}
|
||||
|
||||
if (oldConfig.get('io.ipv4-nossl')) {
|
||||
config.endpoints.push({
|
||||
url: oldConfig.get('io.ipv4-nossl'),
|
||||
secure: false
|
||||
});
|
||||
}
|
||||
|
||||
if (oldConfig.get('io.ipv6-ssl')) {
|
||||
config.endpoints.push({
|
||||
url: oldConfig.get('io.ipv4-ssl'),
|
||||
secure: true,
|
||||
ipv6: true
|
||||
});
|
||||
}
|
||||
|
||||
if (oldConfig.get('io.ipv6-nossl')) {
|
||||
config.endpoints.push({
|
||||
url: oldConfig.get('io.ipv4-nossl'),
|
||||
secure: false,
|
||||
ipv6: true
|
||||
});
|
||||
}
|
||||
|
||||
return new IOConfiguration(config);
|
||||
};
|
14
src/io/cluster/nullclusterclient.js
Normal file
14
src/io/cluster/nullclusterclient.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import Promise from 'bluebird';
|
||||
|
||||
export default class NullClusterClient {
|
||||
constructor(ioConfig) {
|
||||
this.ioConfig = ioConfig;
|
||||
}
|
||||
|
||||
getSocketConfig(channel) {
|
||||
const servers = this.ioConfig.getSocketEndpoints();
|
||||
return Promise.resolve({
|
||||
servers: servers
|
||||
});
|
||||
}
|
||||
}
|
27
src/web/routes/socketconfig.js
Normal file
27
src/web/routes/socketconfig.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import IOConfiguration from '../../configuration/ioconfig';
|
||||
import NullClusterClient from '../../io/cluster/nullclusterclient';
|
||||
import Config from '../../config';
|
||||
import CyTubeUtil from '../../utilities';
|
||||
import Logger from '../../logger';
|
||||
|
||||
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(404).json({
|
||||
error: `Channel "${req.params.channel}" does not exist.`
|
||||
});
|
||||
}
|
||||
|
||||
clusterClient.getSocketConfig(req.params.channel).then(config => {
|
||||
res.json(config);
|
||||
}).catch(err => {
|
||||
Logger.errlog.log(err.stack);
|
||||
return res.status(500).json({
|
||||
error: err.message
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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/<channel name>.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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -1096,27 +1096,57 @@ setupCallbacks = function() {
|
|||
});
|
||||
})(key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
(function () {
|
||||
if (typeof io === "undefined") {
|
||||
makeAlert("Uh oh!", "It appears the connection to <code>" + IO_URL + "</code> " +
|
||||
"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) {
|
||||
if (socketConfig.error) {
|
||||
makeAlert("Error", "Socket.io configuration returned error: " +
|
||||
socketConfig.error, "alert-danger")
|
||||
.appendTo($("#announcements"));
|
||||
return;
|
||||
}
|
||||
|
||||
var chosenServer = null;
|
||||
socketConfig.servers.forEach(function (server) {
|
||||
if (chosenServer === null) {
|
||||
chosenServer = server;
|
||||
} else if (server.secure && !chosenServer.secure) {
|
||||
chosenServer = server;
|
||||
} else if (!server.ipv6Only && chosenServer.ipv6Only) {
|
||||
chosenServer = server;
|
||||
}
|
||||
});
|
||||
|
||||
if (chosenServer === null) {
|
||||
makeAlert("Error",
|
||||
"Socket.io configuration was unable to find a suitable server",
|
||||
"alert-danger")
|
||||
.appendTo($("#announcements"));
|
||||
}
|
||||
|
||||
var opts = {
|
||||
transports: ["websocket", "polling"],
|
||||
secure: chosenServer.secure
|
||||
};
|
||||
|
||||
socket = io(chosenServer.url, opts);
|
||||
setupCallbacks();
|
||||
}).fail(function () {
|
||||
makeAlert("Error", "Failed to retrieve socket.io configuration",
|
||||
"alert-danger")
|
||||
.appendTo($("#announcements"));
|
||||
Callbacks.disconnect();
|
||||
});
|
||||
})();
|
||||
|
|
Loading…
Reference in a new issue