From 6bac45efe29e3947053b7ed55901b7549bdb5ee8 Mon Sep 17 00:00:00 2001 From: John Crepezzi Date: Fri, 18 Nov 2011 15:44:28 -0500 Subject: [PATCH] More work on the server --- .gitignore | 2 + package.json | 50 +++++++++++++++++++++++++ server.js | 86 +++++++++++++++++++++++++++++-------------- static/application.js | 1 + 4 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 .gitignore create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0db216b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +npm-debug.log +node_modules diff --git a/package.json b/package.json new file mode 100644 index 0000000..3dcfc13 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + + "name": "haste", + "version": "0.0.1", + + "private": true, + + "description": "Private Paste", + + "keywords": [ "paste", "pastebin" ], + + "author": { + "name": "John Crepezzi", + "email": "john.crepezzi@gmail.com", + "url": "http://seejohncode.com/" + }, + + "main": "haste", + + "dependencies": { + "winston": "*", + "hashlib": "*" + }, + + "devDependencies": { + "jasmine-node": "*" + }, + + "bundledDependencies": [], + + "engines": { + "node": "*" + }, + + "bin": { + "haste-server": "./server.js" + }, + + "files": [ "server.js", "lib", "static" ], + + "directories": { + "lib": "./lib" + }, + + "scripts": { + "start": "node server.js", + "test": "jasmine-node spec" + } + +} diff --git a/server.js b/server.js index 3e063ab..907a9a7 100644 --- a/server.js +++ b/server.js @@ -3,8 +3,14 @@ var fs = require('fs'); var path = require('path'); var url = require('url'); +var winston = require('winston'); + + +///////////// +// Configure loggin +winston.remove(winston.transports.Console); +winston.add(winston.transports.Console, { colorize: true, level: 'verbose' }); -// TODO logging // TODO preparse static instead of using exists // TODO split into files // TODO only parse url once for static files @@ -21,7 +27,10 @@ StaticHandler.contentTypeFor = function(ext) { else if (ext == '.css') return 'text/css'; else if (ext == '.html') return 'text/html'; else if (ext == '.ico') return 'image/ico'; - else console.log(ext); + else { + winston.error('unable to determine content type for static asset with extension: ' + ext); + return 'text/plain'; + } }; StaticHandler.prototype.handle = function(request, response) { @@ -31,10 +40,9 @@ StaticHandler.prototype.handle = function(request, response) { if (exists) { fs.readFile(filePath, function(error, content) { if (error) { - // TODO make nice - console.log(error); - response.writeHead(500); - response.end(); + winston.error('unable to read file', { path: filePath, error: error.message }); + response.writeHead(500, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ message: 'IO: Unable to read file' })); } else { response.writeHead(200, { 'content-type': StaticHandler.contentTypeFor(path.extname(filePath)) }); @@ -43,9 +51,9 @@ StaticHandler.prototype.handle = function(request, response) { }); } else { - // TODO make nice - response.writeHead(404); - response.end(); + winston.warn('file not found', { path: filePath }); + response.writeHead(404, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ message: 'file not found' })); } }); }; @@ -58,38 +66,62 @@ var DocumentHandler = function() { }; -DocumentHandler.prototype.handle = function(request, response) { - if (request.method == 'GET') { - +DocumentHandler.prototype.handleGet = function(key, response) { + if (documents[key]) { + winston.verbose('retrieved document', { key: key }); + response.writeHead(200, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ data: documents[key] })); } - else if (request.method == 'POST') { - var key = '123'; - request.on('data', function(data) { - if (!documents[key]) { - documents[key] = ''; - } - documents[key] += data.toString(); - }); - request.on('end', function(end) { - response.end(JSON.stringify({ uuid: key })); - }); + else { + winston.warn('document not found', { key: key }); + response.writeHead(400, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ message: 'document not found' })); } }; +DocumentHandler.prototype.handlePost = function(request, response) { + var key = '123'; + request.on('data', function(data) { + if (!documents[key]) { + documents[key] = ''; + } + documents[key] += data.toString(); + }); + request.on('end', function(end) { + winston.verbose('added document', { key: key }); + response.end(JSON.stringify({ uuid: key })); + }); + request.on('error', function(error) { + // TODO handle error + // TODO rename key to uuid everywhere behind the scenes + // TODO finish all TODOs + }); +}; + /////////// http.createServer(function(request, response) { var incoming = url.parse(request.url, false); - var handler = null; - if (incoming.pathname.indexOf('/documents') === 0) { + var match; + + // Looking to add a new doc + if (incoming.pathname.match(/^\/documents$/) && request.method == 'POST') { handler = new DocumentHandler(); + handler.handlePost(request, response); } + + // Looking up a doc + else if ((match = incoming.pathname.match(/^\/documents\/([A-Za-z0-9]+)$/)) && request.method == 'GET') { + handler = new DocumentHandler(); + handler.handleGet(match[1], response); + } + + // Otherwise, look for static file else { handler = new StaticHandler('./static'); + handler.handle(request, response); } - handler.handle(request, response); - }).listen(7777); diff --git a/static/application.js b/static/application.js index 886016f..3d66d75 100644 --- a/static/application.js +++ b/static/application.js @@ -109,6 +109,7 @@ heist.prototype.configureShortcuts = function() { }; +// TODO handle not found gracefully // TODO refuse to lock empty documents // TODO support for browsers without pushstate // TODO support for push state navigation