|
|
@@ -1,94 +1,168 @@
|
|
|
|
|
|
const http = require('http')
|
|
|
- ,fs = require('fs');
|
|
|
+ ,fs = require('fs')
|
|
|
+
|
|
|
+ ,GridManager = require('./GridManager.js');
|
|
|
|
|
|
function HttpServer(config) {
|
|
|
- var ctx = this;
|
|
|
-
|
|
|
- this.config = config;
|
|
|
- this.httpServ = http.createServer(function(req, res) {
|
|
|
- req.reqT = new Date();
|
|
|
- res.ended = false;
|
|
|
- res.once('end', () => {
|
|
|
- res.ended = true;
|
|
|
- });
|
|
|
- if (ctx.isRequestPublic(req.url)) {
|
|
|
- try {
|
|
|
- ctx.servePublic(req.url, res);
|
|
|
- } catch (e) {
|
|
|
- if (e instanceof HttpServer.Error404) {
|
|
|
- res.writeHeader("404", "Not found");
|
|
|
- ctx.servePublic("/404.html", res);
|
|
|
- } else {
|
|
|
- console.error("Unknown error", e);
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- ctx.serveApi(req, res);
|
|
|
- }
|
|
|
- ctx.logRequest(req, res);
|
|
|
- });
|
|
|
+ var ctx = this;
|
|
|
+
|
|
|
+ this.config = config;
|
|
|
+ this.httpServ = http.createServer(function(req, res) {
|
|
|
+ req.reqT = new Date();
|
|
|
+ res.ended = false;
|
|
|
+ res.once('end', () => {
|
|
|
+ res.ended = true;
|
|
|
+ });
|
|
|
+ try {
|
|
|
+ if (ctx.isRequestPublic(req.url)) {
|
|
|
+ ctx.servePublic(req.url, res);
|
|
|
+ } else {
|
|
|
+ var url = req.url.substr(req.url.indexOf("/api/") +5);
|
|
|
+ ctx.serveApi(req, url, res);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ if (e instanceof HttpServer.Error404) {
|
|
|
+ res.writeHeader("404", "Not found");
|
|
|
+ ctx.servePublic("/404.html", res);
|
|
|
+ } else {
|
|
|
+ console.error("Unknown error", e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ctx.logRequest(req, res);
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
HttpServer.prototype.run = function() {
|
|
|
- this.httpServ.listen(this.config.port, () => {
|
|
|
- console.log("[http] listening on " +this.config.port);
|
|
|
- });
|
|
|
+ this.httpServ.listen(this.config.port, () => {
|
|
|
+ console.log("[http] listening on " +this.config.port);
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
HttpServer.prototype.logRequest = function(req, res) {
|
|
|
- console.log("[http] "
|
|
|
- +req.reqT.toISOString()
|
|
|
- +" "
|
|
|
- +req.socket.remoteAddress
|
|
|
- +" "
|
|
|
- +res.statusCode);
|
|
|
+ console.log("[http] "
|
|
|
+ +req.reqT.toISOString()
|
|
|
+ +" "
|
|
|
+ +req.socket.remoteAddress
|
|
|
+ +" "
|
|
|
+ +res.statusCode);
|
|
|
};
|
|
|
|
|
|
HttpServer.prototype.isRequestPublic = function(url) {
|
|
|
- return url.indexOf("/api/") === -1;
|
|
|
+ return url.indexOf("/api/") === -1;
|
|
|
};
|
|
|
|
|
|
HttpServer.prototype.servePublic = function(url, res) {
|
|
|
- url.replace(/\W/g, '');
|
|
|
- var pathTokens = url.split('/')
|
|
|
- ,localPath = './public';
|
|
|
-
|
|
|
- pathTokens.forEach(function(i) {
|
|
|
- i = i.trim();
|
|
|
- if (i != '' && i[0] != '.') {
|
|
|
- localPath += '/' +i;
|
|
|
- }
|
|
|
- });
|
|
|
- var stat;
|
|
|
- try {
|
|
|
- var stat = fs.lstatSync(localPath);
|
|
|
- if (stat.isDirectory()) {
|
|
|
- localPath += "/index.html";
|
|
|
- stat = fs.lstatSync(localPath);
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- throw new HttpServer.Error404(localPath);
|
|
|
- }
|
|
|
- if (!res.headersSent) {
|
|
|
- if (!this.config.isDebug) {
|
|
|
- res.setHeader("Cache-Control", "private, max-age=900");
|
|
|
- }
|
|
|
- res.setHeader("Content-Length", stat.size);
|
|
|
- }
|
|
|
- fs.createReadStream(localPath).pipe(res, { end: true });
|
|
|
+ url.replace(/\W/g, '');
|
|
|
+ var pathTokens = url.split('/')
|
|
|
+ ,localPath = './public';
|
|
|
+
|
|
|
+ pathTokens.forEach(function(i) {
|
|
|
+ i = i.trim();
|
|
|
+ if (i != '' && i[0] != '.') {
|
|
|
+ localPath += '/' +i;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ var stat;
|
|
|
+ try {
|
|
|
+ var stat = fs.lstatSync(localPath);
|
|
|
+ if (stat.isDirectory()) {
|
|
|
+ localPath += "/index.html";
|
|
|
+ stat = fs.lstatSync(localPath);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ throw new HttpServer.Error404(localPath);
|
|
|
+ }
|
|
|
+ if (!res.headersSent) {
|
|
|
+ if (!this.config.isDebug) {
|
|
|
+ res.setHeader("Cache-Control", "private, max-age=900");
|
|
|
+ }
|
|
|
+ res.setHeader("Content-Length", stat.size);
|
|
|
+ }
|
|
|
+ fs.createReadStream(localPath).pipe(res, { end: true });
|
|
|
};
|
|
|
|
|
|
-HttpServer.prototype.serveApi = function(req, res) {
|
|
|
- res.end("Coucou");
|
|
|
+HttpServer.parseUrlParams = function(urlSearch) {
|
|
|
+ var urlToken = {};
|
|
|
+
|
|
|
+ urlSearch.split('&').forEach((token) => {
|
|
|
+ var tokenSplit = token.indexOf('=')
|
|
|
+ ,tokenKey
|
|
|
+ ,tokenValue;
|
|
|
+
|
|
|
+ if (tokenSplit === -1) {
|
|
|
+ tokenKey = token;
|
|
|
+ tokenValue = true;
|
|
|
+ } else {
|
|
|
+ tokenKey = token.substr(0, tokenSplit);
|
|
|
+ tokenValue = token.substr(tokenSplit +1);
|
|
|
+ }
|
|
|
+ if (urlToken[tokenKey]) {
|
|
|
+ urlToken[tokenKey].push(tokenValue);
|
|
|
+ } else {
|
|
|
+ urlToken[tokenKey] = [ tokenValue ];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return urlToken;
|
|
|
+};
|
|
|
+
|
|
|
+HttpServer.prototype.serveApi = function(req, url, res) {
|
|
|
+ var pos = url.indexOf('?')
|
|
|
+ ,urlToken = {};
|
|
|
+
|
|
|
+ if (pos !== -1) {
|
|
|
+ urlToken = HttpServer.parseUrlParams(url.substr(pos +1));
|
|
|
+ url = url.substr(0, pos);
|
|
|
+ }
|
|
|
+ if (url === "create") {
|
|
|
+ // TODO limit grid creation 1 minute by ip
|
|
|
+ var gridId = urlToken["gridId"] ? urlToken["gridId"][0] : null;
|
|
|
+ if (!gridId) {
|
|
|
+ var dd = req.reqT.getDate()
|
|
|
+ ,mm = req.reqT.getMonth() +1
|
|
|
+ ,yy = req.reqT.getFullYear() -2000;
|
|
|
+ gridId = (dd < 10 ? '0' +dd :dd) +(mm < 10 ? '0' +mm : mm) +yy;
|
|
|
+ }
|
|
|
+ GridManager.createGrid(GridManager.hash('' +req.socket.remoteAddress +req.reqT.getTime() +gridId), gridId, (grid)=>{
|
|
|
+ if (grid) {
|
|
|
+ res.setHeader("Location", "/#" +grid.publicId);
|
|
|
+ res.writeHeader("302");
|
|
|
+ } else {
|
|
|
+ res.writeHeader("400", "Bad request");
|
|
|
+ }
|
|
|
+ res.end();
|
|
|
+ });
|
|
|
+ } else if (url === "poll") {
|
|
|
+ if (!urlToken["v"] || !urlToken["grid"]) {
|
|
|
+ res.writeHeader("400", "Bad request");
|
|
|
+ res.end();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var knownVersion = parseFloat(urlToken["v"][0])
|
|
|
+ ,grid = GridManager.get(urlToken["grid"][0]);
|
|
|
+ if (!grid) {
|
|
|
+ throw new HttpServer.Error404();
|
|
|
+ }
|
|
|
+ var data = grid.toStatic(knownVersion);
|
|
|
+ if (data) {
|
|
|
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
|
+ res.end(JSON.stringify(data));
|
|
|
+ } else {
|
|
|
+ res.writeHeader("204");
|
|
|
+ res.end();
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ throw new HttpServer.Error404(url);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
HttpServer.Error404 = function(localPath) {
|
|
|
- console.log("[http] file not found: " +localPath);
|
|
|
+ console.log("[http] file not found: " +localPath);
|
|
|
};
|
|
|
|
|
|
module.exports.serve = function(config) {
|
|
|
- var server = new HttpServer(config);
|
|
|
- server.run();
|
|
|
+ var server = new HttpServer(config);
|
|
|
+ server.run();
|
|
|
};
|
|
|
|