/*\ 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"), http = require("http"); } /* 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 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); }); } Server.prototype.defaultVariables = { port: "8080", host: "127.0.0.1", roottiddler: "$:/core/save/all", rendertype: "text/plain", servetype: "text/html", debuglevel: "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("pathprefix") || ""; for(var t=0; t