mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-05-03 16:04:10 +00:00
Marginally improve the elegance of the simple HTTP server
This commit is contained in:
parent
dbde2bf23b
commit
210f596d0c
@ -12,47 +12,107 @@ Serve tiddlers over http
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
if(!$tw.browser) {
|
||||||
|
var util = require("util"),
|
||||||
|
fs = require("fs"),
|
||||||
|
url = require("url"),
|
||||||
|
path = require("path"),
|
||||||
|
http = require("http");
|
||||||
|
}
|
||||||
|
|
||||||
exports.info = {
|
exports.info = {
|
||||||
name: "server",
|
name: "server",
|
||||||
synchronous: true
|
synchronous: true
|
||||||
};
|
};
|
||||||
|
|
||||||
var Command = function(params,commander,callback) {
|
/*
|
||||||
this.params = params;
|
A simple HTTP server with regexp-based routes
|
||||||
this.commander = commander;
|
*/
|
||||||
this.callback = callback;
|
function SimpleServer(options) {
|
||||||
|
this.routes = options.routes || [];
|
||||||
|
this.wiki = options.wiki;
|
||||||
|
this.variables = options.variables || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleServer.prototype.set = function(obj) {
|
||||||
|
var self = this;
|
||||||
|
$tw.utils.each(obj,function(value,name) {
|
||||||
|
self.variables[name] = value;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Command.prototype.execute = function() {
|
SimpleServer.prototype.get = function(name) {
|
||||||
var self = this,
|
return this.variables[name];
|
||||||
util = require("util"),
|
};
|
||||||
fs = require("fs"),
|
|
||||||
url = require("url"),
|
SimpleServer.prototype.addRoute = function(route) {
|
||||||
path = require("path"),
|
this.routes.push(route);
|
||||||
http = require("http"),
|
};
|
||||||
port = this.params[0] || "8080",
|
|
||||||
rootTiddler = this.params[1] || "$:/core/templates/tiddlywiki5.template.html",
|
SimpleServer.prototype.listen = function(port) {
|
||||||
renderType = this.params[2] || "text/plain",
|
var self = this;
|
||||||
serveType = this.params[3] || "text/html",
|
|
||||||
prefix;
|
|
||||||
http.createServer(function(request, response) {
|
http.createServer(function(request, response) {
|
||||||
var requestPath = url.parse(request.url).pathname,
|
// Compose the state object
|
||||||
text;
|
var state = {};
|
||||||
|
state.wiki = self.wiki;
|
||||||
|
state.server = self;
|
||||||
|
state.urlInfo = url.parse(request.url);
|
||||||
|
// Find the route that matches this path
|
||||||
|
var route;
|
||||||
|
for(var t=0; t<self.routes.length; t++) {
|
||||||
|
var potentialRoute = self.routes[t],
|
||||||
|
pathRegExp = potentialRoute.path,
|
||||||
|
match = potentialRoute.path.exec(state.urlInfo.pathname);
|
||||||
|
if(request.method === potentialRoute.method && match) {
|
||||||
|
state.params = [];
|
||||||
|
for(var p=1; p<match.length; p++) {
|
||||||
|
state.params.push(match[p]);
|
||||||
|
}
|
||||||
|
route = potentialRoute;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return a 404 if we didn't find a route
|
||||||
|
if(!route) {
|
||||||
|
response.writeHead(404);
|
||||||
|
response.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Dispatch the appropriate method
|
||||||
switch(request.method) {
|
switch(request.method) {
|
||||||
|
case "GET": // Intentional fall-through
|
||||||
|
case "DELETE":
|
||||||
|
route.handler(request,response,state);
|
||||||
|
break;
|
||||||
case "PUT":
|
case "PUT":
|
||||||
var data = "";
|
var data = "";
|
||||||
request.on("data",function(chunk) {
|
request.on("data",function(chunk) {
|
||||||
data += chunk.toString();
|
data += chunk.toString();
|
||||||
});
|
});
|
||||||
request.on("end",function() {
|
request.on("end",function() {
|
||||||
prefix = "/recipes/default/tiddlers/";
|
state.data = data;
|
||||||
if(requestPath.indexOf(prefix) === 0) {
|
route.handler(request,response,state);
|
||||||
var title = decodeURIComponent(requestPath.substr(prefix.length)),
|
});
|
||||||
fields = JSON.parse(data);
|
break;
|
||||||
// Use the title from the PUT URL if we don't have one
|
|
||||||
if(!fields.title) {
|
|
||||||
fields.title = title;
|
|
||||||
}
|
}
|
||||||
|
}).listen(port);
|
||||||
|
};
|
||||||
|
|
||||||
|
var Command = function(params,commander,callback) {
|
||||||
|
this.params = params;
|
||||||
|
this.commander = commander;
|
||||||
|
this.callback = callback;
|
||||||
|
// Set up server
|
||||||
|
this.server = new SimpleServer({
|
||||||
|
wiki: this.commander.wiki
|
||||||
|
});
|
||||||
|
// Add route handlers
|
||||||
|
this.server.addRoute({
|
||||||
|
method: "PUT",
|
||||||
|
path: /^\/recipes\/default\/tiddlers\/(.+)$/,
|
||||||
|
handler: function(request,response,state) {
|
||||||
|
var title = decodeURIComponent(state.params[0]),
|
||||||
|
fields = JSON.parse(state.data);
|
||||||
// Pull up any subfields in the `fields` object
|
// Pull up any subfields in the `fields` object
|
||||||
if(fields.fields) {
|
if(fields.fields) {
|
||||||
$tw.utils.each(fields.fields,function(field,name) {
|
$tw.utils.each(fields.fields,function(field,name) {
|
||||||
@ -65,39 +125,40 @@ Command.prototype.execute = function() {
|
|||||||
delete fields["revision"];
|
delete fields["revision"];
|
||||||
}
|
}
|
||||||
console.log("PUT tiddler",title,fields)
|
console.log("PUT tiddler",title,fields)
|
||||||
self.commander.wiki.addTiddler(new $tw.Tiddler(JSON.parse(data),{title: title}));
|
state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title}));
|
||||||
var changeCount = self.commander.wiki.getChangeCount(title).toString();
|
var changeCount = state.wiki.getChangeCount(title).toString();
|
||||||
response.writeHead(204, "OK",{
|
response.writeHead(204, "OK",{
|
||||||
Etag: "\"default/" + title + "/" + changeCount + ":\""
|
Etag: "\"default/" + title + "/" + changeCount + ":\""
|
||||||
});
|
});
|
||||||
response.end();
|
response.end();
|
||||||
} else {
|
}
|
||||||
response.writeHead(404);
|
});
|
||||||
|
this.server.addRoute({
|
||||||
|
method: "DELETE",
|
||||||
|
path: /^\/bags\/default\/tiddlers\/(.+)$/,
|
||||||
|
handler: function(request,response,state) {
|
||||||
|
var title = decodeURIComponent(state.params[0]);
|
||||||
|
console.log("DELETE tiddler",title)
|
||||||
|
state.wiki.deleteTiddler(title);
|
||||||
|
response.writeHead(204, "OK");
|
||||||
response.end();
|
response.end();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
this.server.addRoute({
|
||||||
case "DELETE":
|
method: "GET",
|
||||||
prefix = "/bags/default/tiddlers/";
|
path: /^\/$/,
|
||||||
if(requestPath.indexOf(prefix) === 0) {
|
handler: function(request,response,state) {
|
||||||
var title = decodeURIComponent(requestPath.substr(prefix.length));
|
response.writeHead(200, {"Content-Type": state.server.get("serveType")});
|
||||||
console.log("DELETE tiddler",title)
|
var text = state.wiki.renderTiddler(state.server.get("renderType"),state.server.get("rootTiddler"));
|
||||||
self.commander.wiki.deleteTiddler(decodeURIComponent(title));
|
|
||||||
response.writeHead(204, "OK");
|
|
||||||
response.end();
|
|
||||||
} else {
|
|
||||||
response.writeHead(404);
|
|
||||||
response.end();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "GET":
|
|
||||||
if(requestPath === "/") {
|
|
||||||
response.writeHead(200, {"Content-Type": serveType});
|
|
||||||
text = self.commander.wiki.renderTiddler(renderType,rootTiddler);
|
|
||||||
response.end(text,"utf8");
|
response.end(text,"utf8");
|
||||||
} else if(requestPath === "/status") {
|
}
|
||||||
|
});
|
||||||
|
this.server.addRoute({
|
||||||
|
method: "GET",
|
||||||
|
path: /^\/status$/,
|
||||||
|
handler: function(request,response,state) {
|
||||||
response.writeHead(200, {"Content-Type": "application/json"});
|
response.writeHead(200, {"Content-Type": "application/json"});
|
||||||
text = JSON.stringify({
|
var text = JSON.stringify({
|
||||||
username: "ANONYMOUS",
|
username: "ANONYMOUS",
|
||||||
space: {
|
space: {
|
||||||
recipe: "default"
|
recipe: "default"
|
||||||
@ -105,10 +166,15 @@ console.log("DELETE tiddler",title)
|
|||||||
tiddlywiki_version: $tw.version
|
tiddlywiki_version: $tw.version
|
||||||
});
|
});
|
||||||
response.end(text,"utf8");
|
response.end(text,"utf8");
|
||||||
} else if(requestPath === "/recipes/default/tiddlers.json") {
|
}
|
||||||
|
});
|
||||||
|
this.server.addRoute({
|
||||||
|
method: "GET",
|
||||||
|
path: /^\/recipes\/default\/tiddlers.json$/,
|
||||||
|
handler: function(request,response,state) {
|
||||||
response.writeHead(200, {"Content-Type": "application/json"});
|
response.writeHead(200, {"Content-Type": "application/json"});
|
||||||
var tiddlers = [];
|
var tiddlers = [];
|
||||||
$tw.wiki.forEachTiddler("title",function(title,tiddler) {
|
state.wiki.forEachTiddler("title",function(title,tiddler) {
|
||||||
var tiddlerFields = {};
|
var tiddlerFields = {};
|
||||||
$tw.utils.each(tiddler.fields,function(field,name) {
|
$tw.utils.each(tiddler.fields,function(field,name) {
|
||||||
if(name !== "text") {
|
if(name !== "text") {
|
||||||
@ -118,13 +184,16 @@ console.log("DELETE tiddler",title)
|
|||||||
tiddlerFields["revision"] = $tw.wiki.getChangeCount(title);
|
tiddlerFields["revision"] = $tw.wiki.getChangeCount(title);
|
||||||
tiddlers.push(tiddlerFields);
|
tiddlers.push(tiddlerFields);
|
||||||
});
|
});
|
||||||
text = JSON.stringify(tiddlers);
|
var text = JSON.stringify(tiddlers);
|
||||||
response.end(text,"utf8");
|
response.end(text,"utf8");
|
||||||
} else {
|
}
|
||||||
prefix = "/recipes/default/tiddlers/";
|
});
|
||||||
if(requestPath.indexOf(prefix) === 0) {
|
this.server.addRoute({
|
||||||
var title = decodeURIComponent(requestPath.substr(prefix.length)),
|
method: "GET",
|
||||||
tiddler = $tw.wiki.getTiddler(title),
|
path: /^\/recipes\/default\/tiddlers\/(.+)$/,
|
||||||
|
handler: function(request,response,state) {
|
||||||
|
var title = decodeURIComponent(state.params[0]),
|
||||||
|
tiddler = state.wiki.getTiddler(title),
|
||||||
tiddlerFields = {},
|
tiddlerFields = {},
|
||||||
knownFields = [
|
knownFields = [
|
||||||
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
"bag", "created", "creator", "modified", "modifier", "permissions", "recipe", "revision", "tags", "text", "title", "type", "uri"
|
||||||
@ -145,18 +214,21 @@ console.log("DELETE tiddler",title)
|
|||||||
response.writeHead(404);
|
response.writeHead(404);
|
||||||
response.end();
|
response.end();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
response.writeHead(404);
|
|
||||||
response.end();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
break;
|
};
|
||||||
case "POST":
|
|
||||||
response.writeHead(404);
|
Command.prototype.execute = function() {
|
||||||
response.end();
|
var port = this.params[0] || "8080",
|
||||||
break;
|
rootTiddler = this.params[1] || "$:/core/templates/tiddlywiki5.template.html",
|
||||||
}
|
renderType = this.params[2] || "text/plain",
|
||||||
}).listen(port);
|
serveType = this.params[3] || "text/html";
|
||||||
|
this.server.set({
|
||||||
|
rootTiddler: rootTiddler,
|
||||||
|
renderType: renderType,
|
||||||
|
serveType: serveType
|
||||||
|
});
|
||||||
|
this.server.listen(port);
|
||||||
if(this.commander.verbose) {
|
if(this.commander.verbose) {
|
||||||
console.log("Serving on port " + port);
|
console.log("Serving on port " + port);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user