Compare commits
1 Commits
17320ee1dd
...
6271da2ff3
Author | SHA1 | Date | |
---|---|---|---|
6271da2ff3 |
@ -1,10 +1,9 @@
|
||||
{
|
||||
"host": "0.0.0.0",
|
||||
"port": 7777,
|
||||
"keyLength": 10,
|
||||
"maxLength": 400000,
|
||||
"keyLength": 5,
|
||||
"keySpace": "abcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"staticMaxAge": 86400,
|
||||
"recompressStaticAssets": true,
|
||||
"logging": [
|
||||
{
|
||||
"level": "verbose",
|
||||
|
@ -1,119 +1,102 @@
|
||||
var Busboy = require('busboy');
|
||||
var Winston = require('winston');
|
||||
|
||||
// For handling serving stored documents
|
||||
// For handling serving stored documents.
|
||||
|
||||
var DocumentHandler = function(options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
this.keyLength = options.keyLength || DocumentHandler.defaultKeyLength;
|
||||
this.maxLength = options.maxLength; // none by default
|
||||
var DocumentHandler = function(options = {}) {
|
||||
this.store = options.store;
|
||||
this.keyGenerator = options.keyGenerator;
|
||||
};
|
||||
|
||||
DocumentHandler.defaultKeyLength = 10;
|
||||
|
||||
// Handle retrieving a document
|
||||
// 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' });
|
||||
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.' }));
|
||||
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
|
||||
// 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' });
|
||||
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.' }));
|
||||
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
|
||||
// Handle adding a new document.
|
||||
DocumentHandler.prototype.handlePost = function (request, response) {
|
||||
var _this = this;
|
||||
var buffer = '';
|
||||
var buffer = "";
|
||||
var cancelled = false;
|
||||
|
||||
// What to do when done
|
||||
// If success...
|
||||
var onSuccess = function () {
|
||||
// Check length
|
||||
if (_this.maxLength && buffer.length > _this.maxLength) {
|
||||
cancelled = true;
|
||||
Winston.warn('document >maxLength', { maxLength: _this.maxLength });
|
||||
response.writeHead(400, { 'content-type': 'application/json' });
|
||||
response.end(
|
||||
JSON.stringify({ message: 'Document exceeds maximum length.' })
|
||||
);
|
||||
return;
|
||||
}
|
||||
// And then save if we should
|
||||
_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' });
|
||||
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.' }));
|
||||
Winston.verbose("Error adding document");
|
||||
response.writeHead(500, { "content-type": "application/json" });
|
||||
response.end(JSON.stringify({ message: "Error adding document." }));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// If we should, parse a form to grab the data
|
||||
var ct = request.headers['content-type'];
|
||||
if (ct && ct.split(';')[0] === 'multipart/form-data') {
|
||||
// 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') {
|
||||
busboy.on("field", function (fieldname, val) {
|
||||
if (fieldname === "data") {
|
||||
buffer = val;
|
||||
}
|
||||
});
|
||||
busboy.on('finish', function () {
|
||||
busboy.on("finish", function () {
|
||||
onSuccess();
|
||||
});
|
||||
request.pipe(busboy);
|
||||
// Otherwise, use our own and just grab flat data from POST body
|
||||
// Otherwise, use our own and just grab flat data from POST body.
|
||||
} else {
|
||||
request.on('data', function (data) {
|
||||
request.on("data", function (data) {
|
||||
buffer += data.toString();
|
||||
});
|
||||
request.on('end', function () {
|
||||
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.' }));
|
||||
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 one isn't taken
|
||||
// Keep choosing keys until we find one that isn't taken.
|
||||
DocumentHandler.prototype.chooseKey = function(callback) {
|
||||
var key = this.acceptableKey();
|
||||
var _this = this;
|
||||
@ -123,11 +106,11 @@ DocumentHandler.prototype.chooseKey = function(callback) {
|
||||
} else {
|
||||
callback(key);
|
||||
}
|
||||
}, true); // Don't bump expirations when key searching
|
||||
}, true); // Don't bump expirations when key searching.
|
||||
};
|
||||
|
||||
DocumentHandler.prototype.acceptableKey = function() {
|
||||
return this.keyGenerator.createKey(this.keyLength);
|
||||
return this.keyGenerator.createKey();
|
||||
};
|
||||
|
||||
module.exports = DocumentHandler;
|
||||
|
@ -1,23 +1,23 @@
|
||||
var fs = require('fs');
|
||||
var crypto = require('crypto');
|
||||
var fs = require("fs");
|
||||
var crypto = require("crypto");
|
||||
|
||||
var FileDocumentStore = function() {
|
||||
this.basePath = '/data';
|
||||
this.basePath = "/data";
|
||||
this.expire = null;
|
||||
};
|
||||
|
||||
FileDocumentStore.md5 = function(str) {
|
||||
var md5sum = crypto.createHash('md5');
|
||||
var md5sum = crypto.createHash("md5");
|
||||
md5sum.update(str);
|
||||
return md5sum.digest('hex');
|
||||
return md5sum.digest("hex");
|
||||
};
|
||||
|
||||
FileDocumentStore.prototype.set = function(key, data, callback) {
|
||||
try {
|
||||
var _this = this;
|
||||
fs.mkdir(this.basePath, '700', function() {
|
||||
var fn = _this.basePath + '/' + FileDocumentStore.md5(key);
|
||||
fs.writeFile(fn, data, 'utf8', function(err) {
|
||||
fs.mkdir(this.basePath, "700", function() {
|
||||
var fn = _this.basePath + "/" + FileDocumentStore.md5(key);
|
||||
fs.writeFile(fn, data, "utf8", function(err) {
|
||||
if (err) {
|
||||
callback(false);
|
||||
}
|
||||
@ -33,8 +33,8 @@ FileDocumentStore.prototype.set = function(key, data, callback) {
|
||||
|
||||
FileDocumentStore.prototype.get = function(key, callback) {
|
||||
var _this = this;
|
||||
var fn = _this.basePath + '/' + FileDocumentStore.md5(key);
|
||||
fs.readFile(fn, 'utf8', function(err, data) {
|
||||
var fn = _this.basePath + "/" + FileDocumentStore.md5(key);
|
||||
fs.readFile(fn, "utf8", function(err, data) {
|
||||
if (err) {
|
||||
callback(false);
|
||||
}
|
||||
|
@ -1,19 +1,18 @@
|
||||
module.exports = class KeyGenerator {
|
||||
|
||||
// Initialize a new generator with the given keySpace
|
||||
constructor() {
|
||||
this.keyspace = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
// Initialise a new generator with the given key space.
|
||||
constructor(options = {}) {
|
||||
this.keyLength = options.keyLength;
|
||||
this.keySpace = options.keySpace;
|
||||
}
|
||||
|
||||
// Generate a key of the given length
|
||||
createKey(keyLength) {
|
||||
var text = '';
|
||||
|
||||
for (var i = 0; i < keyLength; i++) {
|
||||
const index = Math.floor(Math.random() * this.keyspace.length);
|
||||
text += this.keyspace.charAt(index);
|
||||
// Generate a key of the given length.
|
||||
createKey() {
|
||||
var text = "";
|
||||
for (var i = 0; i < this.keyLength; i++) {
|
||||
const index = Math.floor(Math.random() * this.keySpace.length);
|
||||
text += this.keySpace.charAt(index);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,6 @@
|
||||
"connect": "3.4.1",
|
||||
"st": "1.1.0",
|
||||
"winston": "0.6.2",
|
||||
"redis-url": "0.1.0",
|
||||
"redis": "0.8.1",
|
||||
"uglify-js": "3.1.6",
|
||||
"busboy": "0.2.4",
|
||||
"pg": "4.1.1"
|
||||
},
|
||||
|
70
server.js
70
server.js
@ -1,25 +1,25 @@
|
||||
var Connect = require('connect');
|
||||
var ConnectSt = require('st');
|
||||
var Fs = require('fs');
|
||||
var Http = require('http');
|
||||
var Route = require('connect-route');
|
||||
var Winston = require('winston');
|
||||
var Connect = require("connect");
|
||||
var ConnectSt = require("st");
|
||||
var Fs = require("fs");
|
||||
var Http = require("http");
|
||||
var Route = require("connect-route");
|
||||
var Winston = require("winston");
|
||||
|
||||
var DocumentHandler = require('./lib/document_handler');
|
||||
var KeyGenerator = require('./lib/key_generator');
|
||||
var Store = require('./lib/document_store');
|
||||
var DocumentHandler = require("./lib/document_handler");
|
||||
var KeyGenerator = require("./lib/key_generator");
|
||||
var Store = require("./lib/document_store");
|
||||
|
||||
// Load the configuration and set some defaults
|
||||
var config = JSON.parse(Fs.readFileSync('./config.js', 'utf8'));
|
||||
config.host = config.host || '127.0.0.1';
|
||||
// Load the configuration and set some defaults.
|
||||
var config = JSON.parse(Fs.readFileSync("./config.js", "utf8"));
|
||||
config.host = config.host || "127.0.0.1";
|
||||
config.port = config.port || 7777;
|
||||
|
||||
// Set up the logger
|
||||
// Set up the logger.
|
||||
if (config.logging) {
|
||||
try {
|
||||
Winston.remove(Winston.transports.Console);
|
||||
} catch(e) {
|
||||
// This is fine
|
||||
// This is fine.
|
||||
}
|
||||
var detail, type;
|
||||
for (var i = 0; i < config.logging.length; i++) {
|
||||
@ -30,60 +30,62 @@ if (config.logging) {
|
||||
}
|
||||
}
|
||||
|
||||
// Configure the data store
|
||||
// Configure the data store.
|
||||
store = new Store();
|
||||
|
||||
// Pick up a key generator
|
||||
var keyGenerator = new KeyGenerator();
|
||||
// Pick up a key generator.
|
||||
var keyGenerator = new KeyGenerator({
|
||||
keyLength: config.keyLength,
|
||||
keySpace: config.keySpace
|
||||
});
|
||||
|
||||
// Configure the document handler
|
||||
// Configure the document handler.
|
||||
var documentHandler = new DocumentHandler({
|
||||
store: store,
|
||||
maxLength: config.maxLength,
|
||||
keyLength: config.keyLength,
|
||||
keyGenerator: keyGenerator
|
||||
});
|
||||
|
||||
var app = Connect();
|
||||
|
||||
// API
|
||||
// Configure the API routes.
|
||||
app.use(Route(function(router) {
|
||||
router.get('/raw/:id', function(request, response) {
|
||||
var key = request.params.id.split('.')[0];
|
||||
router.get("/raw/:id", function(request, response) {
|
||||
var key = request.params.id.split(".")[0];
|
||||
return documentHandler.handleRawGet(key, response);
|
||||
});
|
||||
router.post('/documents', function(request, response) {
|
||||
router.post("/documents", function(request, response) {
|
||||
return documentHandler.handlePost(request, response);
|
||||
});
|
||||
router.get('/documents/:id', function(request, response) {
|
||||
var key = request.params.id.split('.')[0];
|
||||
router.get("/documents/:id", function(request, response) {
|
||||
var key = request.params.id.split(".")[0];
|
||||
return documentHandler.handleGet(key, response);
|
||||
});
|
||||
}));
|
||||
|
||||
// Static files
|
||||
// Route static files.
|
||||
app.use(ConnectSt({
|
||||
path: __dirname + '/static',
|
||||
path: __dirname + "/static",
|
||||
content: { maxAge: config.staticMaxAge },
|
||||
passthrough: true,
|
||||
index: false
|
||||
}));
|
||||
|
||||
// All the pastebin IDs
|
||||
// All the pastebin IDs.
|
||||
app.use(Route(function(router) {
|
||||
router.get('/:id', function(request, response, next) {
|
||||
request.sturl = '/';
|
||||
router.get("/:id", function(request, response, next) {
|
||||
request.sturl = "/";
|
||||
next();
|
||||
});
|
||||
}));
|
||||
|
||||
// Index
|
||||
// Route index.html.
|
||||
app.use(ConnectSt({
|
||||
path: __dirname + '/static',
|
||||
path: __dirname + "/static",
|
||||
content: { maxAge: config.staticMaxAge },
|
||||
index: 'index.html'
|
||||
index: "index.html"
|
||||
}));
|
||||
|
||||
Http.createServer(app).listen(config.port, config.host);
|
||||
|
||||
Winston.info('Listening on ' + config.host + ':' + config.port);
|
||||
Winston.info("Listening on " + config.host + ":" + config.port);
|
||||
|
Loading…
x
Reference in New Issue
Block a user