From daabcf7dcd79120205b1eaf8a53cd33e889e86fc Mon Sep 17 00:00:00 2001 From: zneix Date: Fri, 28 Aug 2020 04:46:48 +0200 Subject: [PATCH] Config rewrite --- .eslintignore | 1 + .gitignore | 3 +- README.md | 2 +- config.js | 31 -------- example.config.js | 48 +++++++++++++ server.js | 179 +++++++++++++++++++++++----------------------- 6 files changed, 141 insertions(+), 123 deletions(-) delete mode 100644 config.js create mode 100644 example.config.js diff --git a/.eslintignore b/.eslintignore index 5e08342..244da91 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ **/*.min.js config.js +example.config.js \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8460900..847fd1c 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ data *.DS_Store npm-debug.log -static/*.min.js \ No newline at end of file +static/*.min.js +config.js \ No newline at end of file diff --git a/README.md b/README.md index e228365..5c6a014 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ STDOUT. Check the README there for more details and usages. * `keyLength` - the length of the keys to user (default 10) * `maxLength` - maximum length of a paste (default 400000) * `staticMaxAge` - max age for static assets (86400) -* `recompressStaticAssets` - whether or not to compile static js assets (true) +* `compressStaticAssets` - whether or not to compile static js assets (true) * `documents` - static documents to serve (ex: http://hastebin.com/about.md) in addition to static assets. These will never expire. * `storage` - storage options (see below) diff --git a/config.js b/config.js deleted file mode 100644 index 8d9f891..0000000 --- a/config.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = { - "host": "127.0.0.1", - "port": 4200, - - "keyLength": 10, - "maxLength": 400000, - - "staticMaxAge": 60 * 60 * 24, - - "recompressStaticAssets": true, - - "logging": [], //re-add this feature later - - "keyGenerator": { - "type": "phonetic" - }, - - "rateLimits": { - "windowMs": 60 * 60 * 1000, - "max": 500 - }, - - "storage": { - "type": "file", - "path": "./data" - }, - - "documents": { - "about": "./about.md" - } -} \ No newline at end of file diff --git a/example.config.js b/example.config.js new file mode 100644 index 0000000..3668304 --- /dev/null +++ b/example.config.js @@ -0,0 +1,48 @@ +module.exports = { + //address and port to which server will bind, host can also be a hostname + "host": "127.0.0.1", + "port": 7777, + + //length of random characters in link that's generated on document save + "keyLength": 10, + //max allowed paste length - 0 for unlimited + "maxLength": 400000, + + //algorithm used to generate random characters + //see docs/generators.md for more information + "keyGenerator": { + "type": "phonetic" + }, + + //max age for static website assets + "staticMaxAge": 60 * 60 * 24, + + //whether or not to minify static js scripts which load faster for end-users + "compressStaticAssets": true, + + //TODO: re-add more options to logging + //logging preferences + "logging": { + //can be one of: error, warn, info, http, verbose, debug, silly + "level": "info" + }, + + //rate limits for requests, handled by express-rate-limit + //options can be found here: https://github.com/nfriedly/express-rate-limit/blob/master/lib/express-rate-limit.js#L7-L14 + "rateLimits": { + "windowMs": 30 * 60 * 1000, + "max": 250 + }, + + //storage system used for storing saved haste documents + //see docs/storage.md for more information + "storage": { + "type": "file", + "path": "./data" + }, + + //static documents that will never expire ("name": "path") + "documents": { + "about": "./about.md" + } +}; \ No newline at end of file diff --git a/server.js b/server.js index 0372f57..7ce4164 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,5 @@ -const fs = require('fs'); const winston = require('winston'); +const fs = require('fs'); const minify = require('babel-minify'); const st = require('st'); const app = require('express')(); @@ -11,13 +11,12 @@ const HasteUtils = require('./lib/util'); const utils = new HasteUtils(); //set up logger -//only Console for now, gotta utilize config.json in the future winston.add(new winston.transports.Console({ - level: 'silly', - format: winston.format.combine( - winston.format.colorize(), - winston.format.printf(info => `${info.level}: ${info.message} ${utils.stringifyJSONMessagetoLogs(info)}`) - ), + level: config.logging.level, + format: winston.format.combine( + winston.format.colorize(), + winston.format.printf(info => `${info.level}: ${info.message} ${utils.stringifyJSONMessagetoLogs(info)}`) + ), })); //load config and set some defaults @@ -27,113 +26,113 @@ config.host = config.host || '127.0.0.1'; //defaulting storage type to file if (!config.storage){ - config.storage = { - type: 'file', - path: './data' - }; + config.storage = { + type: 'file', + path: './data' + }; } if (!config.storage.type) config.storage.type = 'file'; let preferredStore; if (process.env.REDISTOGO_URL && config.storage.type == 'redis'){ - let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL); - let Store = require('./lib/document_stores/redis'); - preferredStore = new Store(config.storage, redisClient); + let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL); + let Store = require('./lib/document_stores/redis'); + preferredStore = new Store(config.storage, redisClient); } else { - let Store = require(`./lib/document_stores/${config.storage.type}`); - preferredStore = new Store(config.storage); + let Store = require(`./lib/document_stores/${config.storage.type}`); + preferredStore = new Store(config.storage); } //compress static javascript assets -if (config.recompressStaticAssets){ - let files = fs.readdirSync('./static'); - //https://regex101.com/r/5cJagJ/2 - for (const file of files){ - let info = file.match(/^((.+)(? winston.debug('loaded static document', { success: doc }), true); - } - else { - winston.warn('failed to load static document', { name: name, path: path }); - } -} + //send the static documents into the preferred store, skipping expirations + for (const name in config.documents){ + let path = config.documents[name]; + winston.info('loading static document', { name: name, path: path }); + let data = fs.readFileSync(path, 'utf8'); + if (data){ + await preferredStore.set(name, data, doc => winston.debug('loaded static document', { success: doc }), true); + } + else { + winston.warn('failed to load static document', { name: name, path: path }); + } + } -//pick up a key generator -let pwOptions = config.keyGenerator || new Object; -pwOptions.type = pwOptions.type || 'random'; -let Gen = require(`./lib/key_generators/${pwOptions.type}`); -let keyGenerator = new Gen(pwOptions); + //pick up a key generator + let pwOptions = config.keyGenerator || new Object; + pwOptions.type = pwOptions.type || 'random'; + let Gen = require(`./lib/key_generators/${pwOptions.type}`); + let keyGenerator = new Gen(pwOptions); -//configure the document handler -let documentHandler = new DocumentHandler({ - store: preferredStore, - maxLength: config.maxLength, - keyLength: config.keyLength, - keyGenerator: keyGenerator -}); + //configure the document handler + let documentHandler = new DocumentHandler({ + store: preferredStore, + maxLength: config.maxLength, + keyLength: config.keyLength, + keyGenerator: keyGenerator + }); -//rate limit all requests -if (config.rateLimits) app.use(expressRateLimit(config.rateLimits)); + //rate limit all requests + if (config.rateLimits) app.use(expressRateLimit(config.rateLimits)); -//try API first + //try API first -//get raw documents -app.get('/raw/:id', async (req, res) => { - const key = req.params.id.split('.')[0]; - const skipExpire = Boolean(config.documents[key]); - return await documentHandler.handleGetRaw(key, res, skipExpire); -}); + //get raw documents + app.get('/raw/:id', async (req, res) => { + const key = req.params.id.split('.')[0]; + const skipExpire = Boolean(config.documents[key]); + return await documentHandler.handleGetRaw(key, res, skipExpire); + }); -//add documents -app.post('/documents', async (req, res) => { - return await documentHandler.handlePost(req, res); -}); + //add documents + app.post('/documents', async (req, res) => { + return await documentHandler.handlePost(req, res); + }); -//get documents -app.get('/documents/:id', async (req, res) => { - const key = req.params.id.split('.')[0]; - const skipExpire = Boolean(config.documents[key]); - return await documentHandler.handleGet(key, res, skipExpire); -}); + //get documents + app.get('/documents/:id', async (req, res) => { + const key = req.params.id.split('.')[0]; + const skipExpire = Boolean(config.documents[key]); + return await documentHandler.handleGet(key, res, skipExpire); + }); -//try static next -app.use(st({ - path: './static', - passthrough: true, - index: false -})); + //try static next + app.use(st({ + path: './static', + passthrough: true, + index: false + })); -//then we can loop back - and everything else should be a token, -//so route it back to / -app.get('/:id', (req, res, next) => { - req.sturl = '/'; - next(); -}); + //then we can loop back - and everything else should be a token, + //so route it back to / + app.get('/:id', (req, res, next) => { + req.sturl = '/'; + next(); + }); -//and match index -app.use(st({ - content: { maxAge: config.staticMaxAge }, - path: './static', - index: 'index.html' -})); + //and match index + app.use(st({ + content: { maxAge: config.staticMaxAge }, + path: './static', + index: 'index.html' + })); -app.listen(config.port, config.host, () => winston.info(`listening on ${config.host}:${config.port}`)); + app.listen(config.port, config.host, () => winston.info(`listening on ${config.host}:${config.port}`)); })(); \ No newline at end of file