var http = require('http'), fs = require('fs'), path = require('path'), bee = require('beeline'), qs = require('querystring'), hl = require(__dirname + '/highlight'), tmpl = require(__dirname + '/templates'), pasteInit = require(__dirname + '/paste'); var config = { port: 8080, database: __dirname + '/../db/pastes.kch' }; var paste; function _200(res, contentType, data) { res.writeHead(200, {'Content-Type': contentType}); res.write(data); res.end('\n'); } function _302(res, url) { res.writeHead(302, {'Location': url}); res.end(); } 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 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)) { fs.lstat(file, function(err, stat) { if (stat.isFile()) { 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 { _404(res); } }); } else { _404(res); } } 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); } }); }, "r`^/static/(.+)$`": function(req, res, filepath) { serveStaticFiles(res, filepath[0]); }, "/add": { POST: function(req, res) { parsePost(req, function(post) { paste.add(post, function(err, id) { if (err) { _500(res, err); } else { console.log('new paste: %s', id); _302(res, '/get/' + id); } }); }); }, GET: function(req, res) { _404(res); } }, "`404`": function(req, res) { _404(res); }, "`503`": function(req, res, err) { _500(res, 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(); }