API changes, add documentation

This commit is contained in:
calzoneman 2015-10-25 17:20:39 -07:00
parent 7b5476874d
commit 21c3a1b3cd
6 changed files with 124 additions and 32 deletions

19
NEWS.md
View file

@ -1,25 +1,12 @@
2015-10-19
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`. The response will look similar to
`/socketconfig/<channel name>.json`. See [the
documentation](docs/socketconfig.md) for more information.
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
==========

57
docs/socketconfig.md Normal file
View 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
bettle 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.

View file

@ -3,21 +3,45 @@ export default class IOConfiguration {
this.config = config;
}
getSocketURL() {
return this.config.urls[0];
getSocketEndpoints() {
return this.config.endpoints.slice();
}
}
IOConfiguration.fromOldConfig = function (oldConfig) {
const config = {
urls: []
endpoints: []
};
['ipv4-ssl', 'ipv4-nossl', 'ipv6-ssl', 'ipv6-nossl'].forEach(key => {
if (oldConfig.get('io.' + key)) {
config.urls.push(oldConfig.get('io.' + key));
}
});
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);
};

View file

@ -6,10 +6,9 @@ export default class NullClusterClient {
}
getSocketConfig(channel) {
const url = this.ioConfig.getSocketURL();
const servers = this.ioConfig.getSocketEndpoints();
return Promise.resolve({
url: url,
secure: /^(https|wss)/.test(url)
servers: servers
});
}
}

View file

@ -2,6 +2,7 @@ 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);
@ -9,13 +10,18 @@ export default function initialize(app) {
app.get('/socketconfig/:channel.json', (req, res) => {
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
return res.status(400).json({
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
});
});
});
}

View file

@ -1112,21 +1112,40 @@ setupCallbacks = function() {
$.getJSON("/socketconfig/" + CHANNEL.name + ".json")
.done(function (socketConfig) {
if (socketConfig.error) {
makeAlert("Socket.io configuration returned 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: socketConfig.secure
secure: chosenServer.secure
};
socket = io(socketConfig.url, opts);
socket = io(chosenServer.url, opts);
setupCallbacks();
}).fail(function () {
makeAlert("Failed to retrieve socket.io configuration", "alert-danger")
makeAlert("Error", "Failed to retrieve socket.io configuration",
"alert-danger")
.appendTo($("#announcements"));
Callbacks.disconnect();
});