mirror of https://github.com/calzoneman/sync.git
Web refactoring
This commit is contained in:
parent
566e932e7e
commit
50ca141f1d
1
index.js
1
index.js
|
@ -3,6 +3,7 @@ try {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('FATAL: Failed to require() lib/server.js');
|
console.error('FATAL: Failed to require() lib/server.js');
|
||||||
console.error('Have you run `npm run build-server` yet to generate it?');
|
console.error('Have you run `npm run build-server` yet to generate it?');
|
||||||
|
console.error(err.stack);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
var Config = require("./lib/config");
|
var Config = require("./lib/config");
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import createError from 'create-error';
|
import createError from 'create-error';
|
||||||
|
import * as HTTPStatus from './web/httpstatus';
|
||||||
|
|
||||||
export const ChannelStateSizeError = createError('ChannelStateSizeError');
|
export const ChannelStateSizeError = createError('ChannelStateSizeError');
|
||||||
export const ChannelNotFoundError = createError('ChannelNotFoundError');
|
export const ChannelNotFoundError = createError('ChannelNotFoundError');
|
||||||
|
export const CSRFError = createError('CSRFError');
|
||||||
|
export const HTTPError = createError('HTTPError', {
|
||||||
|
status: HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
|
});
|
||||||
|
|
|
@ -42,6 +42,9 @@ var $util = require("./utilities");
|
||||||
var db = require("./database");
|
var db = require("./database");
|
||||||
var Flags = require("./flags");
|
var Flags = require("./flags");
|
||||||
var sio = require("socket.io");
|
var sio = require("socket.io");
|
||||||
|
import LocalChannelIndex from './web/localchannelindex';
|
||||||
|
import IOConfiguration from './configuration/ioconfig';
|
||||||
|
import NullClusterClient from './io/cluster/nullclusterclient';
|
||||||
|
|
||||||
var Server = function () {
|
var Server = function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -60,8 +63,14 @@ var Server = function () {
|
||||||
ChannelStore.init();
|
ChannelStore.init();
|
||||||
|
|
||||||
// webserver init -----------------------------------------------------
|
// webserver init -----------------------------------------------------
|
||||||
|
const ioConfig = IOConfiguration.fromOldConfig(Config);
|
||||||
|
const clusterClient = new NullClusterClient(ioConfig);
|
||||||
|
const channelIndex = new LocalChannelIndex();
|
||||||
self.express = express();
|
self.express = express();
|
||||||
require("./web/webserver").init(self.express);
|
require("./web/webserver").init(self.express,
|
||||||
|
ioConfig,
|
||||||
|
clusterClient,
|
||||||
|
channelIndex);
|
||||||
|
|
||||||
// http/https/sio server init -----------------------------------------
|
// http/https/sio server init -----------------------------------------
|
||||||
var key = "", cert = "", ca = undefined;
|
var key = "", cert = "", ca = undefined;
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
* Adapted from https://github.com/expressjs/csurf
|
* Adapted from https://github.com/expressjs/csurf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { CSRFError } from '../errors';
|
||||||
|
|
||||||
var csrf = require("csrf");
|
var csrf = require("csrf");
|
||||||
var createError = require("http-errors");
|
|
||||||
|
|
||||||
var tokens = csrf();
|
var tokens = csrf();
|
||||||
|
|
||||||
|
@ -39,8 +40,6 @@ exports.verify = function csrfVerify(req) {
|
||||||
var token = req.body._csrf || req.query._csrf;
|
var token = req.body._csrf || req.query._csrf;
|
||||||
|
|
||||||
if (!tokens.verify(secret, token)) {
|
if (!tokens.verify(secret, token)) {
|
||||||
throw createError(403, 'invalid csrf token', {
|
throw new CSRFError('Invalid CSRF token');
|
||||||
code: 'EBADCSRFTOKEN'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export const BAD_REQUEST = 400;
|
||||||
|
export const FORBIDDEN = 403;
|
||||||
|
export const INTERNAL_SERVER_ERROR = 500;
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Promise from 'bluebird';
|
||||||
|
import Server from '../server';
|
||||||
|
|
||||||
|
var SERVER = null;
|
||||||
|
|
||||||
|
export default class LocalChannelIndex {
|
||||||
|
listPublicChannels() {
|
||||||
|
if (SERVER === null) {
|
||||||
|
SERVER = require('../server').getServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.resolve(SERVER.packChannelList(true));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
import CyTubeUtil from '../../utilities';
|
||||||
|
import { sanitizeText } from '../../xss';
|
||||||
|
import { sendJade } from '../jade';
|
||||||
|
import * as HTTPStatus from '../httpstatus';
|
||||||
|
import { HTTPError } from '../../errors';
|
||||||
|
|
||||||
|
export default function initialize(app, ioConfig) {
|
||||||
|
app.get('/r/:channel', (req, res) => {
|
||||||
|
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
|
||||||
|
throw new HTTPError(`"${sanitizeText(req.params.channel)} is not a valid ` +
|
||||||
|
'channel name.', { status: HTTPStatus.BAD_REQUEST });
|
||||||
|
}
|
||||||
|
|
||||||
|
const endpoints = ioConfig.getSocketEndpoints();
|
||||||
|
if (endpoints.length === 0) {
|
||||||
|
throw new HTTPError('No socket.io endpoints configured');
|
||||||
|
}
|
||||||
|
const socketBaseURL = endpoints[0].url;
|
||||||
|
|
||||||
|
sendJade(res, 'channel', {
|
||||||
|
channelName: req.params.channel,
|
||||||
|
sioSource: `${socketBaseURL}/socket.io/socket.io.js`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { sendJade } from '../jade';
|
||||||
|
|
||||||
|
export default function initialize(app, channelIndex) {
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
channelIndex.listPublicChannels().then((channels) => {
|
||||||
|
channels.sort((a, b) => {
|
||||||
|
if (a.usercount === b.usercount) {
|
||||||
|
return a.uniqueName > b.uniqueName ? -1 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.usercount - a.usercount;
|
||||||
|
});
|
||||||
|
|
||||||
|
sendJade(res, 'index', {
|
||||||
|
channels: channels
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,16 +1,12 @@
|
||||||
import IOConfiguration from '../../configuration/ioconfig';
|
|
||||||
import NullClusterClient from '../../io/cluster/nullclusterclient';
|
|
||||||
import Config from '../../config';
|
import Config from '../../config';
|
||||||
import CyTubeUtil from '../../utilities';
|
import CyTubeUtil from '../../utilities';
|
||||||
import Logger from '../../logger';
|
import Logger from '../../logger';
|
||||||
|
import * as HTTPStatus from '../httpstatus';
|
||||||
|
|
||||||
export default function initialize(app) {
|
export default function initialize(app, clusterClient) {
|
||||||
const ioConfig = IOConfiguration.fromOldConfig(Config);
|
|
||||||
const clusterClient = new NullClusterClient(ioConfig);
|
|
||||||
|
|
||||||
app.get('/socketconfig/:channel.json', (req, res) => {
|
app.get('/socketconfig/:channel.json', (req, res) => {
|
||||||
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
|
if (!req.params.channel || !CyTubeUtil.isValidChannelName(req.params.channel)) {
|
||||||
return res.status(404).json({
|
return res.status(HTTPStatus.NOT_FOUND).json({
|
||||||
error: `Channel "${req.params.channel}" does not exist.`
|
error: `Channel "${req.params.channel}" does not exist.`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ var morgan = require("morgan");
|
||||||
var session = require("../session");
|
var session = require("../session");
|
||||||
var csrf = require("./csrf");
|
var csrf = require("./csrf");
|
||||||
var XSS = require("../xss");
|
var XSS = require("../xss");
|
||||||
|
import * as HTTPStatus from './httpstatus';
|
||||||
|
import { CSRFError } from '../errors';
|
||||||
|
|
||||||
const LOG_FORMAT = ':real-address - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';
|
const LOG_FORMAT = ':real-address - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"';
|
||||||
morgan.token('real-address', function (req) { return req._ip; });
|
morgan.token('real-address', function (req) { return req._ip; });
|
||||||
|
@ -71,51 +73,6 @@ function redirectHttp(req, res) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a GET request for /r/:channel - serves channel.html
|
|
||||||
*/
|
|
||||||
function handleChannel(req, res) {
|
|
||||||
if (!$util.isValidChannelName(req.params.channel)) {
|
|
||||||
res.status(404);
|
|
||||||
res.send("Invalid channel name '" + XSS.sanitizeText(req.params.channel) + "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var sio;
|
|
||||||
if (net.isIPv6(ipForRequest(req))) {
|
|
||||||
sio = Config.get("io.ipv6-default");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sio) {
|
|
||||||
sio = Config.get("io.ipv4-default");
|
|
||||||
}
|
|
||||||
|
|
||||||
sio += "/socket.io/socket.io.js";
|
|
||||||
|
|
||||||
sendJade(res, "channel", {
|
|
||||||
channelName: req.params.channel,
|
|
||||||
sioSource: sio
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a request for the index page
|
|
||||||
*/
|
|
||||||
function handleIndex(req, res) {
|
|
||||||
var channels = Server.getServer().packChannelList(true);
|
|
||||||
channels.sort(function (a, b) {
|
|
||||||
if (a.usercount === b.usercount) {
|
|
||||||
return a.uniqueName > b.uniqueName ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.usercount - a.usercount;
|
|
||||||
});
|
|
||||||
|
|
||||||
sendJade(res, "index", {
|
|
||||||
channels: channels
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Legacy socket.io configuration endpoint. This is being migrated to
|
* Legacy socket.io configuration endpoint. This is being migrated to
|
||||||
* /socketconfig/<channel name>.json (see ./routes/socketconfig.js)
|
* /socketconfig/<channel name>.json (see ./routes/socketconfig.js)
|
||||||
|
@ -185,7 +142,7 @@ module.exports = {
|
||||||
/**
|
/**
|
||||||
* Initializes webserver callbacks
|
* Initializes webserver callbacks
|
||||||
*/
|
*/
|
||||||
init: function (app) {
|
init: function (app, ioConfig, clusterClient, channelIndex) {
|
||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
req._ip = ipForRequest(req);
|
req._ip = ipForRequest(req);
|
||||||
next();
|
next();
|
||||||
|
@ -241,10 +198,10 @@ module.exports = {
|
||||||
Logger.syslog.log("Enabled express-minify for CSS and JS");
|
Logger.syslog.log("Enabled express-minify for CSS and JS");
|
||||||
}
|
}
|
||||||
|
|
||||||
app.get("/r/:channel", handleChannel);
|
require("./routes/channel")(app, ioConfig);
|
||||||
app.get("/", handleIndex);
|
require("./routes/index")(app, channelIndex);
|
||||||
app.get("/sioconfig(.json)?", handleSocketConfig);
|
app.get("/sioconfig(.json)?", handleSocketConfig);
|
||||||
require("./routes/socketconfig")(app);
|
require("./routes/socketconfig")(app, clusterClient);
|
||||||
app.get("/useragreement", handleUserAgreement);
|
app.get("/useragreement", handleUserAgreement);
|
||||||
app.get("/contact", handleContactPage);
|
app.get("/contact", handleContactPage);
|
||||||
require("./auth").init(app);
|
require("./auth").init(app);
|
||||||
|
@ -256,21 +213,24 @@ module.exports = {
|
||||||
}));
|
}));
|
||||||
app.use(function (err, req, res, next) {
|
app.use(function (err, req, res, next) {
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err.message && err.message.match(/failed to decode param/i)) {
|
if (err instanceof CSRFError) {
|
||||||
return res.status(400).send("Malformed path: " + req.path);
|
res.status(HTTPStatus.FORBIDDEN);
|
||||||
} else if (err.message && err.message.match(/range not satisfiable/i)) {
|
return sendJade(res, 'csrferror', { path: req.path });
|
||||||
return res.status(416).end();
|
|
||||||
} else if (err.message && err.message.match(/request entity too large/i)) {
|
|
||||||
return res.status(413).end();
|
|
||||||
} else if (err.message && err.message.match(/bad request/i)) {
|
|
||||||
return res.status(400).end("Bad Request");
|
|
||||||
} else if (err.message && err.message.match(/invalid csrf token/i)) {
|
|
||||||
res.status(403);
|
|
||||||
sendJade(res, 'csrferror', { path: req.path });
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let { message, status } = err;
|
||||||
|
if (!status) {
|
||||||
|
status = HTTPStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
}
|
||||||
|
if (!message) {
|
||||||
|
message = 'An unknown error occurred.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.floor(status / 100) === 5) {
|
||||||
Logger.errlog.log(err.stack);
|
Logger.errlog.log(err.stack);
|
||||||
res.status(500).end();
|
}
|
||||||
|
|
||||||
|
return res.status(status).send(message);
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue