From ec2f803a306c7843a8814029b5e77a9dadffd136 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Thu, 30 Jun 2011 23:48:38 +0200 Subject: progress: templates/css, new router, paste module as db abstraction --- lib/main.js | 236 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 75 deletions(-) (limited to 'lib/main.js') diff --git a/lib/main.js b/lib/main.js index 6e2f36a..191dbaa 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,103 +1,189 @@ var http = require('http'), -router = require('choreographer').router(), +fs = require('fs'), +path = require('path'), +bee = require('beeline'), qs = require('querystring'), -uuid = require(__dirname + '/uuid'), hl = require(__dirname + '/highlight'), -kyoto = require('kyoto'); +tmpl = require(__dirname + '/templates'), +pasteInit = require(__dirname + '/paste'); -var db = new kyoto.open(__dirname + '/../db/pastes.kch', 'a+', kyotoOpen); +var config = { + port: 8080, + database: __dirname + '/../db/pastes.kch' +}; -function generateId(callback) { - var id = uuid.generate(14); - db.get(id, function(err, value) { - if (value) { - generateId(); - } - else { - callback(id); - } +var paste; + +function _200(res, contentType, data) { + res.writeHead(200, {'Content-Type': contentType}); + res.write(data); + res.end('\n'); +} + +function _404(res) { + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.end('404: Not found.\n'); +} + +function _500(res, err) { + res.writeHead(404, {'Content-Type': 'text/plain'}); + res.write('500: Internal Server Error'); + + if (err) { + res.write(':\n'); + res.write(JSON.stringify(err)); + } + + res.end('\n'); +} + +function parsePost(req, callback) { + var content = ''; + + req.on('data', function(chunk) { + content += chunk; + }); + + req.on('end', function() { + var post = qs.parse(content); + callback(post); }); } -function getPaste(plain, req, res, paste) { - db.get(paste, function(err, value) { - if (err) { - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.end('404: ' + req.url + ' not found:\n' + err + '\n'); - } - else { - var data = JSON.parse(value); - if (plain) { - res.writeHead(200, {'Content-Type': 'text/plain'}); - res.write(data.content); +function getContentType(ext) { + contentType = { + '.css': 'text/css', + '.js': 'text/javascript', + '.png': 'image/png' + }; + + if (contentType[ext]) { + return contentType[ext]; + } + else { + return 'unknown'; + } +} + +function checkPath(file, base) { + var normFile = path.normalize(file); + var normBase = path.normalize(base); + + if (normFile.indexOf(normBase) === 0) { + return true; + } + else { + return false; + } +} + +function serveStaticFiles(res, filepath) { + var base = path.join(__dirname, '..', 'static'); + var file = path.join(base, filepath); + + if (checkPath(file, base)) { + path.exists(file, function(exists) { + if (exists) { + var ext = path.extname(file); + var contentType = getContentType(ext); + + fs.readFile(file, function (err, data) { + if (err) { + _500(res, err); + } + else { + _200(res, contentType, data); + } + }); } else { - res.writeHead(200, {'Content-Type': 'text/html'}); - res.write(hl.highlight(data.content, data.language)); + _404(res); } - res.end('\n'); - } - }); + }); + } + else { + _404(res); + } } -router - .get('/plain/*', function(req, res, paste) { - getPaste(true, req, res, paste); - }) - .get('/get/*', function(req, res, paste) { - getPaste(false, req, res, paste); - }) - .get('/', function(req, res) { - }) - .post('/add', function(req, res) { - var content = ''; - - req.on('data', function(chunk) { - content += chunk; +var router = bee.route({ + "/": function(req, res) { + tmpl.renderHtml('submit-form.tmpl', {}, res); + }, + + "r`^/plain/([^/]+)$`": function(req, res, id) { + paste.get(id[0], function(data) { + if (data) { + _200(res, 'text/plain', data.content); + } + else { + _404(res); + } + }); + }, + + "r`^/get/([^/]+)$`": function(req, res, id) { + paste.get(id[0], function(data) { + if (data) { + data.styles = [{name: '/static/highlight/github.css'}]; + data.content = hl.highlight(data.content, data.language); + + tmpl.renderHtml('paste.tmpl', data, res); + } + else { + _404(res); + } }); + }, - req.on('end', function() { - var post = qs.parse(content); + "r`^/static/(.+)$`": function(req, res, filepath) { + serveStaticFiles(res, filepath[0]); + }, - generateId(function(id) { - var data = { - content: post.content, - language: post.language, - time: Date() - }; - db.set(id, JSON.stringify(data), function(err) { + "/add": { + POST: function(req, res) { + parsePost(req, function(post) { + paste.add(post, function(err, id) { if (err) { - res.writeHead(500, {'Content-Type': 'text/plain'}); - res.write(err); - res.end('\n'); + _500(res, err); } else { console.log('new paste: %s', id); - res.writeHead(200, {'Content-Type': 'text/plain'}); - res.write(id); - res.end('\n'); + tmpl.renderHtml('newPaste.tmpl', {id: id}, res); } }); }); - }); - }) - .notFound(function(req, res) { - res.writeHead(404, {'Content-Type': 'text/plain'}); - res.end('404: ' + req.url + ' not found.\n'); - }); - + }, -function kyotoOpen(err) { - if (err) throw err; + GET: function(req, res) { + _404(res); + } + }, - http.createServer(router).listen(8080); - console.log('Listening on port 8080...'); -} + "`404`": function(req, res) { + _404(res); + }, -process.on('uncaughtException', function(exeption) { - process.exit(1); + "`503`": function(req, res, err) { + _500(res, err); + } }); -process.on('exit', function() { - db.close(function(err) { console.log(err); }); -}); +var server = function(port) { + port = port || config.port; + + pasteInit.init(config, function(func) { + paste = func; + + http.createServer(router).listen(port); + console.log('Listening on port %d...', port); + }); +}; + +if (typeof module == "object" && typeof require == "function") { + exports.server = server; + exports.config = config; +} +if (module === require.main) { + server(); +} -- cgit v1.2.3