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
config.js
example.config.js

3
.gitignore vendored
View File

@ -7,4 +7,5 @@ data
*.DS_Store
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)
* `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)

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 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(/^((.+)(?<!\.min)(\.js))$/);
if (!info) continue;
const dest = `${info[2]}.min${info[3]}`;
const code = fs.readFileSync(`./static/${file}`, 'utf8');
const {code: newCode} = minify(code);
fs.writeFileSync(`./static/${dest}`, newCode, 'utf8');
winston.info(`compressed ${file} into ${dest}`);
}
if (config.compressStaticAssets){
let files = fs.readdirSync('./static');
//https://regex101.com/r/5cJagJ/2
for (const file of files){
let info = file.match(/^((.+)(?<!\.min)(\.js))$/);
if (!info) continue;
const dest = `${info[2]}.min${info[3]}`;
const code = fs.readFileSync(`./static/${file}`, 'utf8');
const {code: newCode} = minify(code);
fs.writeFileSync(`./static/${dest}`, newCode, 'utf8');
winston.info(`compressed ${file} into ${dest}`);
}
}
(async function(){
//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 });
}
}
//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}`));
})();