Created
November 28, 2010 20:24
-
-
Save Ming-Tang/719273 to your computer and use it in GitHub Desktop.
node.js wiki
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var http = require('http'), | |
url = require('url'), | |
fs = require('fs'), | |
qs = require('querystring'); | |
const MAINPAGE = 'MainPage'; | |
function clean(x) { | |
return x.replace(/[^a-zA-Z0-9_-]/g, ''); | |
} | |
function ent(x) { | |
return x.replace('&', '&').replace('<', '<').replace('"', '"'); | |
} | |
function tt(title) { | |
return clean(title[0] || '') || MAINPAGE; | |
} | |
function errorPage(request, response, e) { | |
response.writeHead(500, {'Content-Type': 'text/plain'}); | |
response.end(e + ""); | |
} | |
function header(title) { | |
/* SYNTAX: | |
return | |
"str" | |
=> | |
return; | |
"str"; | |
*/ | |
return "" | |
+ "<!DOCTYPE html><html><head><title>" | |
+ title | |
+ "</title></head>"; | |
} | |
function parsePost(p) { | |
pairs = p.split('&'); | |
var res = { }; | |
for (var i = 0; i < p.length; i ++) { | |
var pair = pairs[i].split('='); | |
res[unescape(pair[0])] = unescape(pair[1]); | |
} | |
return res; | |
} | |
function redirect(request, response, url, body) { | |
response.writeHead(301, {'Content-Type': 'text/html', 'Location': url}); | |
response.end(body || ""); | |
} | |
var handlers = { | |
page: function(title, request, response) { | |
title = tt(title); | |
var mtime, data; | |
l: { | |
try { | |
mtime = fs.statSync(title + ".html").mtime; | |
data = fs.readFileSync(title + ".html", 'UTF-8'); | |
break l; | |
} catch (e) { | |
response.writeHead(404, {'Content-Type': 'text/html'}); | |
response.end( | |
header(title) | |
+ "<body><div class='nopage'>" | |
+ "<p>" + e + "</p>" | |
+ "<p><em>This page does not exist. Do you want to create it?</em></p>" | |
+ "<a href='/edit/" + title + "'>Create This Page</a></body>" | |
); | |
} | |
} | |
var ctime = request.headers['if-modified-since']; | |
if (new Date(mtime).getTime() <= new Date(ctime).getTime()) { | |
response.writeHead(304, {'Content-Type': 'text/html'}); | |
response.end(); | |
} else { | |
response.writeHead(200, {'Content-Type': 'text/html', 'Cache-Control': 'must-revalidate', 'Last-Modified': mtime}); | |
response.end( | |
header(title) | |
+ "<body><div class='page'><article><header><h1>" | |
+ title | |
+ "</h1><header>" | |
+ data | |
+ "</article><hr />" | |
+ "<nav><a href='/edit/" + title + "'>Edit</a> | " | |
+ "<a href='/delete/" + title + "'>Delete</a></nav></div></body></html>"); | |
} | |
}, | |
edit: function(title, request, response) { | |
title = tt(title); | |
var data, newPage = false; | |
try { | |
data = fs.readFileSync(title + ".html", 'UTF-8'); | |
} catch (e) { | |
data = ""; | |
newPage = true; | |
} | |
response.writeHead(200, {'Content-Type': 'text/html'}); | |
response.end( | |
header(title) | |
+ "<body><div class='edit'><form action='/submit/" + title + "' method='post'><h1>" | |
+ (newPage ? "Creating " : "Editing ") | |
+ title | |
+ "</h1><textarea name='text' cols='80' rows='40'>" | |
+ ent(data) | |
+ "</textarea><br /><input type='submit' value='Submit' name='Submit' /></form><hr />" | |
+ "<nav><a href='/page/" + title + "'>< Return</a> | " | |
+ "<a href='/delete/" + title + "'>Delete</a></nav></div></body></html>"); | |
}, | |
submit: function(title, request, response) { | |
title = tt(title); | |
if (request.method == 'POST') { | |
var buf = ''; | |
request.on('data', function(chunk) { | |
buf += chunk.toString(); | |
}); | |
request.on('end', function() { | |
try { | |
var t = qs.parse(buf).text || ""; | |
var f = fs.openSync(title + ".html", 'w') | |
fs.writeSync(f, t, 0); | |
fs.closeSync(f); | |
redirect(request, response, '/page/' + title); | |
} catch (e) { | |
errorPage(request, response, e); | |
} | |
}); | |
} else { | |
redirect(request, response, '/page/' + title); | |
} | |
}, | |
delete: function(title, request, response) { | |
title = tt(title); | |
response.writeHead(200, {'Content-Type': 'text/html'}); | |
response.end( | |
header(title) | |
+ "<body><div class='delete'>" | |
+ "<p>Do you really want to delete the page <em>" + title + "</em>?</p>" | |
+ "<a href='/page/" + title + "'>< No</a> | " | |
+ "<a href='/deleting/" + title + "'>Yes</a></div></body></html>"); | |
}, | |
deleting: function(title, request, response) { | |
title = tt(title); | |
fs.unlinkSync(title + ".html"); | |
redirect(request, response, '/page/' + MAINPAGE); | |
} | |
} | |
http.createServer(function(request, response) { | |
var info = url.parse(request.url).pathname.substr(1).split('/'); | |
console.log(info); | |
if (info.length == 1 && info[0] == '') { | |
response.writeHead(301, {'Location': '/page/' + MAINPAGE}); | |
response.end(); | |
return; | |
} | |
var name = info[0]; | |
try { | |
if (typeof handlers[name] == 'function') { | |
handlers[name](info.slice(1), request, response); | |
} else if (info.length == 1) { | |
redirect(request, response, '/page/' + name) | |
} else { | |
response.writeHead(404, {'Content-Type': 'text/plain'}); | |
response.end("404 Not Found"); | |
} | |
} catch (e) { | |
errorPage(request, response, e); | |
console.log(e); | |
} | |
}).listen(8124); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p>Hello, world!</p> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment