var Busboy = require('busboy'); var Winston = require('winston'); // For handling serving stored documents. var DocumentHandler = function(options = {}) { this.store = options.store; this.keyGenerator = options.keyGenerator; }; // Handle retrieving a document. DocumentHandler.prototype.handleGet = function(key, response) { this.store.get(key, function(ret) { if (ret) { Winston.verbose("Retrieved document.", { key: key }); response.writeHead(200, { "content-type": "application/json" }); response.end(JSON.stringify({ data: ret, key: key })); } else { Winston.warn("Document not found.", { key: key }); response.writeHead(404, { "content-type": "application/json" }); response.end(JSON.stringify({ message: "Document not found." })); } }); }; // Handle retrieving the raw version of a document. DocumentHandler.prototype.handleRawGet = function(key, response) { this.store.get(key, function(ret) { if (ret) { Winston.verbose("Retrieved raw document.", { key: key }); response.writeHead(200, { "content-type": "text/plain; charset=UTF-8" }); response.end(ret); } else { Winston.warn("Raw document not found.", { key: key }); response.writeHead(404, { "content-type": "application/json" }); response.end(JSON.stringify({ message: "Document not found." })); } }); }; // Handle adding a new document. DocumentHandler.prototype.handlePost = function (request, response) { var _this = this; var buffer = ""; var cancelled = false; // If success... var onSuccess = function () { _this.chooseKey(function (key) { _this.store.set(key, buffer, function (res) { if (res) { Winston.verbose("Added document.", { key: key }); response.writeHead(200, { "content-type": "application/json" }); response.end(JSON.stringify({ key: key })); } else { Winston.verbose("Error adding document"); response.writeHead(500, { "content-type": "application/json" }); response.end(JSON.stringify({ message: "Error adding document." })); } }); }); }; // Parse form to grab the data. var ct = request.headers["content-type"]; if (ct && ct.split(";")[0] === "multipart/form-data") { var busboy = new Busboy({ headers: request.headers }); busboy.on("field", function (fieldname, val) { if (fieldname === "data") { buffer = val; } }); busboy.on("finish", function () { onSuccess(); }); request.pipe(busboy); // Otherwise, use our own and just grab flat data from POST body. } else { request.on("data", function (data) { buffer += data.toString(); }); request.on("end", function () { if (cancelled) { return; } onSuccess(); }); request.on("error", function (error) { Winston.error("Connection error: " + error.message); response.writeHead(500, { "content-type": "application/json" }); response.end(JSON.stringify({ message: "Connection error." })); cancelled = true; }); } }; // Keep choosing keys until we find one that isn't taken. DocumentHandler.prototype.chooseKey = function(callback) { var key = this.acceptableKey(); var _this = this; this.store.get(key, function(ret) { if (ret) { _this.chooseKey(callback); } else { callback(key); } }, true); // Don't bump expirations when key searching. }; DocumentHandler.prototype.acceptableKey = function() { return this.keyGenerator.createKey(); }; module.exports = DocumentHandler;