/*\ title: $:/core/modules/server/server.js type: application/javascript module-type: library Serve tiddlers over http \*/ (function(){ /*jslint node: true, browser: true */ /*global $tw: false */ "use strict"; if($tw.node) { var util = require("util"), fs = require("fs"), url = require("url"), path = require("path"); } /* A simple HTTP server with regexp-based routes options: variables - optional hashmap of variables to set (a misnomer - they are really constant parameters) routes - optional array of routes to use wiki - reference to wiki object */ function Server(options) { var self = this; this.routes = options.routes || []; this.authenticators = options.authenticators || []; this.wiki = options.wiki; this.servername = this.wiki.getTiddlerText("$:/SiteTitle") || "TiddlyWiki5"; // Initialise the variables this.variables = $tw.utils.extend({},this.defaultVariables); if(options.variables) { for(var variable in options.variables) { if(options.variables[variable]) { this.variables[variable] = options.variables[variable]; } } } $tw.utils.extend({},this.defaultVariables,options.variables); // Initialise CSRF this.csrfDisable = this.get("csrf-disable") === "yes"; // Initialise authorization var authorizedUserName = (this.get("username") && this.get("password")) ? this.get("username") : "(anon)"; this.authorizationPrincipals = { readers: (this.get("readers") || authorizedUserName).split(",").map($tw.utils.trim), writers: (this.get("writers") || authorizedUserName).split(",").map($tw.utils.trim) } // Load and initialise authenticators $tw.modules.forEachModuleOfType("authenticator", function(title,authenticatorDefinition) { // console.log("Loading server route " + title); self.addAuthenticator(authenticatorDefinition.AuthenticatorClass); }); // Load route handlers $tw.modules.forEachModuleOfType("route", function(title,routeDefinition) { // console.log("Loading server route " + title); self.addRoute(routeDefinition); }); // Initialise the http vs https this.listenOptions = {}; this.protocol = "http"; var tlsKeyFilepath = this.get("tls-key"), tlsCertFilepath = this.get("tls-cert"); if(tlsCertFilepath && tlsKeyFilepath) { this.listenOptions.key = fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsKeyFilepath),"utf8"); this.listenOptions.cert = fs.readFileSync(path.resolve($tw.boot.wikiPath,tlsCertFilepath),"utf8"); this.protocol = "https"; } this.transport = require(this.protocol); } Server.prototype.defaultVariables = { port: "8080", host: "127.0.0.1", "root-tiddler": "$:/core/save/all", "root-render-type": "text/plain", "root-serve-type": "text/html", "tiddler-render-type": "text/html", "tiddlertemplate": "$:/core/templates/server/static.tiddler.html", "system-tiddler-render-type": "text/plain", "system-tiddler-template": "$:/core/templates/wikified-tiddler", "debug-level": "none" }; Server.prototype.get = function(name) { return this.variables[name]; }; Server.prototype.addRoute = function(route) { this.routes.push(route); }; Server.prototype.addAuthenticator = function(AuthenticatorClass) { // Instantiate and initialise the authenticator var authenticator = new AuthenticatorClass(this), result = authenticator.init(); if(typeof result === "string") { $tw.utils.error("Error: " + result); } else if(result) { // Only use the authenticator if it initialised successfully this.authenticators.push(authenticator); } }; Server.prototype.findMatchingRoute = function(request,state) { var pathprefix = this.get("path-prefix") || ""; for(var t=0; t