1
0
Fork 0
mirror of https://github.com/SunRed/haste-server.git synced 2024-11-23 17:50:19 +01:00

Config rewrite

This commit is contained in:
zneix 2020-08-28 04:46:48 +02:00
parent e4eeec3d27
commit daabcf7dcd
6 changed files with 141 additions and 123 deletions

View file

@ -1,2 +1,3 @@
**/*.min.js **/*.min.js
config.js config.js
example.config.js

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ data
npm-debug.log npm-debug.log
static/*.min.js static/*.min.js
config.js

View file

@ -40,7 +40,7 @@ STDOUT. Check the README there for more details and usages.
* `keyLength` - the length of the keys to user (default 10) * `keyLength` - the length of the keys to user (default 10)
* `maxLength` - maximum length of a paste (default 400000) * `maxLength` - maximum length of a paste (default 400000)
* `staticMaxAge` - max age for static assets (86400) * `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) * `documents` - static documents to serve (ex: http://hastebin.com/about.md)
in addition to static assets. These will never expire. in addition to static assets. These will never expire.
* `storage` - storage options (see below) * `storage` - storage options (see below)

View file

@ -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"
}
}

48
example.config.js Normal file
View file

@ -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"
}
};

179
server.js
View file

@ -1,5 +1,5 @@
const fs = require('fs');
const winston = require('winston'); const winston = require('winston');
const fs = require('fs');
const minify = require('babel-minify'); const minify = require('babel-minify');
const st = require('st'); const st = require('st');
const app = require('express')(); const app = require('express')();
@ -11,13 +11,12 @@ const HasteUtils = require('./lib/util');
const utils = new HasteUtils(); const utils = new HasteUtils();
//set up logger //set up logger
//only Console for now, gotta utilize config.json in the future
winston.add(new winston.transports.Console({ winston.add(new winston.transports.Console({
level: 'silly', level: config.logging.level,
format: winston.format.combine( format: winston.format.combine(
winston.format.colorize(), winston.format.colorize(),
winston.format.printf(info => `${info.level}: ${info.message} ${utils.stringifyJSONMessagetoLogs(info)}`) winston.format.printf(info => `${info.level}: ${info.message} ${utils.stringifyJSONMessagetoLogs(info)}`)
), ),
})); }));
//load config and set some defaults //load config and set some defaults
@ -27,113 +26,113 @@ config.host = config.host || '127.0.0.1';
//defaulting storage type to file //defaulting storage type to file
if (!config.storage){ if (!config.storage){
config.storage = { config.storage = {
type: 'file', type: 'file',
path: './data' path: './data'
}; };
} }
if (!config.storage.type) config.storage.type = 'file'; if (!config.storage.type) config.storage.type = 'file';
let preferredStore; let preferredStore;
if (process.env.REDISTOGO_URL && config.storage.type == 'redis'){ if (process.env.REDISTOGO_URL && config.storage.type == 'redis'){
let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL); let redisClient = require('redis-url').connect(process.env.REDISTOGO_URL);
let Store = require('./lib/document_stores/redis'); let Store = require('./lib/document_stores/redis');
preferredStore = new Store(config.storage, redisClient); preferredStore = new Store(config.storage, redisClient);
} }
else { else {
let Store = require(`./lib/document_stores/${config.storage.type}`); let Store = require(`./lib/document_stores/${config.storage.type}`);
preferredStore = new Store(config.storage); preferredStore = new Store(config.storage);
} }
//compress static javascript assets //compress static javascript assets
if (config.recompressStaticAssets){ if (config.compressStaticAssets){
let files = fs.readdirSync('./static'); let files = fs.readdirSync('./static');
//https://regex101.com/r/5cJagJ/2 //https://regex101.com/r/5cJagJ/2
for (const file of files){ for (const file of files){
let info = file.match(/^((.+)(?<!\.min)(\.js))$/); let info = file.match(/^((.+)(?<!\.min)(\.js))$/);
if (!info) continue; if (!info) continue;
const dest = `${info[2]}.min${info[3]}`; const dest = `${info[2]}.min${info[3]}`;
const code = fs.readFileSync(`./static/${file}`, 'utf8'); const code = fs.readFileSync(`./static/${file}`, 'utf8');
const {code: newCode} = minify(code); const {code: newCode} = minify(code);
fs.writeFileSync(`./static/${dest}`, newCode, 'utf8'); fs.writeFileSync(`./static/${dest}`, newCode, 'utf8');
winston.info(`compressed ${file} into ${dest}`); winston.info(`compressed ${file} into ${dest}`);
} }
} }
(async function(){ (async function(){
//send the static documents into the preferred store, skipping expirations //send the static documents into the preferred store, skipping expirations
for (const name in config.documents){ for (const name in config.documents){
let path = config.documents[name]; let path = config.documents[name];
winston.info('loading static document', { name: name, path: path }); winston.info('loading static document', { name: name, path: path });
let data = fs.readFileSync(path, 'utf8'); let data = fs.readFileSync(path, 'utf8');
if (data){ if (data){
await preferredStore.set(name, data, doc => winston.debug('loaded static document', { success: doc }), true); await preferredStore.set(name, data, doc => winston.debug('loaded static document', { success: doc }), true);
} }
else { else {
winston.warn('failed to load static document', { name: name, path: path }); winston.warn('failed to load static document', { name: name, path: path });
} }
} }
//pick up a key generator //pick up a key generator
let pwOptions = config.keyGenerator || new Object; let pwOptions = config.keyGenerator || new Object;
pwOptions.type = pwOptions.type || 'random'; pwOptions.type = pwOptions.type || 'random';
let Gen = require(`./lib/key_generators/${pwOptions.type}`); let Gen = require(`./lib/key_generators/${pwOptions.type}`);
let keyGenerator = new Gen(pwOptions); let keyGenerator = new Gen(pwOptions);
//configure the document handler //configure the document handler
let documentHandler = new DocumentHandler({ let documentHandler = new DocumentHandler({
store: preferredStore, store: preferredStore,
maxLength: config.maxLength, maxLength: config.maxLength,
keyLength: config.keyLength, keyLength: config.keyLength,
keyGenerator: keyGenerator keyGenerator: keyGenerator
}); });
//rate limit all requests //rate limit all requests
if (config.rateLimits) app.use(expressRateLimit(config.rateLimits)); if (config.rateLimits) app.use(expressRateLimit(config.rateLimits));
//try API first //try API first
//get raw documents //get raw documents
app.get('/raw/:id', async (req, res) => { app.get('/raw/:id', async (req, res) => {
const key = req.params.id.split('.')[0]; const key = req.params.id.split('.')[0];
const skipExpire = Boolean(config.documents[key]); const skipExpire = Boolean(config.documents[key]);
return await documentHandler.handleGetRaw(key, res, skipExpire); return await documentHandler.handleGetRaw(key, res, skipExpire);
}); });
//add documents //add documents
app.post('/documents', async (req, res) => { app.post('/documents', async (req, res) => {
return await documentHandler.handlePost(req, res); return await documentHandler.handlePost(req, res);
}); });
//get documents //get documents
app.get('/documents/:id', async (req, res) => { app.get('/documents/:id', async (req, res) => {
const key = req.params.id.split('.')[0]; const key = req.params.id.split('.')[0];
const skipExpire = Boolean(config.documents[key]); const skipExpire = Boolean(config.documents[key]);
return await documentHandler.handleGet(key, res, skipExpire); return await documentHandler.handleGet(key, res, skipExpire);
}); });
//try static next //try static next
app.use(st({ app.use(st({
path: './static', path: './static',
passthrough: true, passthrough: true,
index: false index: false
})); }));
//then we can loop back - and everything else should be a token, //then we can loop back - and everything else should be a token,
//so route it back to / //so route it back to /
app.get('/:id', (req, res, next) => { app.get('/:id', (req, res, next) => {
req.sturl = '/'; req.sturl = '/';
next(); next();
}); });
//and match index //and match index
app.use(st({ app.use(st({
content: { maxAge: config.staticMaxAge }, content: { maxAge: config.staticMaxAge },
path: './static', path: './static',
index: 'index.html' 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}`));
})(); })();