You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.js 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. var app = require('http').createServer(handler)
  2. , sockets = require('./sockets.js')
  3. , path = require('path')
  4. , url = require('url')
  5. , nodestatic = require("node-static")
  6. , createSVG = require("./createSVG.js");
  7. var io = sockets.start(app);
  8. /**
  9. * Folder from which static files will be served
  10. * @const
  11. * @type {string}
  12. */
  13. var WEBROOT = path.join(__dirname, "../client-data");
  14. /**
  15. * Port on which the application will listen
  16. * @const
  17. * @type {number}
  18. */
  19. var PORT = parseInt(process.env['PORT']) || 8080;
  20. app.listen(PORT);
  21. console.log("Server listening on " + PORT);
  22. var CSP = "default-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' ws: wss:";
  23. var fileserver = new nodestatic.Server(WEBROOT, {
  24. "headers": {
  25. "X-UA-Compatible": "IE=Edge",
  26. "Content-Security-Policy": CSP,
  27. }
  28. });
  29. function serveError(request, response, err) {
  30. console.warn("Error serving '" + request.url + "' : " + err.status + " " + err.message);
  31. fileserver.serveFile('error.html', err.status, {}, request, response);
  32. }
  33. function logRequest(request) {
  34. console.log(JSON.stringify({
  35. event: 'connection',
  36. ip: request.connection.remoteAddress,
  37. original_ip: request.headers['x-forwarded-for'] || request.headers['forwarded'],
  38. user_agent: request.headers['user-agent'],
  39. referer: request.headers['referer'],
  40. url: request.url,
  41. time: Date.now()
  42. }));
  43. }
  44. function handler(request, response) {
  45. try {
  46. handleRequest(request, response);
  47. } catch (err) {
  48. console.trace(err);
  49. response.writeHead(500, { 'Content-Type': 'text/plain' });
  50. response.end(err.toString());
  51. }
  52. }
  53. function handleRequest(request, response) {
  54. var parsedUrl = url.parse(request.url, true);
  55. var parts = parsedUrl.pathname.split('/');
  56. if (parts[0] === '') parts.shift();
  57. if (parts.length === 0) {
  58. fileserver.serveFile("index.html", 200, {}, request, response);
  59. logRequest(request);
  60. } else if (parts[0] === "boards") {
  61. // "boards" refers to the root directory
  62. if (parts.length === 1 && parsedUrl.query.board) {
  63. // '/boards?board=...' This allows html forms to point to boards
  64. var headers = { Location: 'boards/' + encodeURIComponent(parsedUrl.query.board) };
  65. response.writeHead(301, headers);
  66. response.end();
  67. } else if (parts.length === 2 && request.url.indexOf('.') === -1) {
  68. // If there is no dot and no directory, parts[1] is the board name
  69. fileserver.serveFile("board.html", 200, {}, request, response);
  70. logRequest(request);
  71. } else { // Else, it's a resource
  72. request.url = "/" + parts.slice(1).join('/');
  73. fileserver.serve(request, response, function (err, res) {
  74. if (err) serveError(request, response, err);
  75. });
  76. }
  77. } else if (parts[0] === "download") {
  78. var boardName = encodeURIComponent(parts[1]),
  79. history_file = "../server-data/board-" + boardName + ".json",
  80. headers = {
  81. "Content-Type": "application/json",
  82. "Content-Disposition": 'attachment; filename="' + boardName + '.wbo"'
  83. };
  84. var promise = fileserver.serveFile(history_file, 200, headers, request, response);
  85. promise.on("error", function (err) {
  86. console.error("Error while downloading history", err);
  87. response.statusCode = 404;
  88. response.end("ERROR: Unable to serve history file\n");
  89. });
  90. } else if (parts[0] === "preview") {
  91. var boardName = encodeURIComponent(parts[1]),
  92. history_file = path.join(__dirname, "..", "server-data", "board-" + boardName + ".json");
  93. createSVG.renderBoard(history_file, function (err, svg) {
  94. if (err) {
  95. response.writeHead(404, { 'Content-Type': 'application/json' });
  96. response.end(JSON.stringify(err));
  97. }
  98. response.writeHead(200, {
  99. "Content-Type": "image/svg+xml",
  100. "Content-Security-Policy": CSP,
  101. });
  102. response.end(svg);
  103. });
  104. } else {
  105. fileserver.serve(request, response, function (err, res) {
  106. if (err) serveError(request, response, err);
  107. });
  108. }
  109. }