const KeyGenerator = require('./key_generator.js'); // handles creating new and requesting existing documents class DocumentHandler { constructor(options) { if (!options) { options = {}; } this.store = options.store; this.logger = options.logger; this.maxLength = options.maxLength || 50000; this.keyLength = options.keyLength || 10; this.createKey = options.createKey || ''; this.keyGenerator = new KeyGenerator(); if (this.createKey !== '') { this.logger.info("Creation-Key is configured."); } } // handles existing documents handleGet(key, res) { this.store.get(key, (ret) => { if (ret) { this.logger.verbose(`Open paste: ${key}`); res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify({ key: key, data: ret.replace(/\t/g, ' ') })); } else { this.logger.verbose(`Paste not found: ${key}`); res.writeHead(404, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Paste not found.' })); } }); } // handles existing documents (raw) handleRawGet(key, res) { this.store.get(key, (ret) => { if (ret) { this.logger.verbose(`Open raw paste: ${key}`); res.writeHead(200, { 'content-type': 'text/plain; charset=utf-8' }); res.end(ret); } else { this.logger.verbose(`Paste not found: ${key}`); res.writeHead(404, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Paste not found.' })); } }); } // handles creating new documents handlePost(req, res) { let buffer = ''; let cancelled = false; req.on('data', (data) => { if (cancelled) return; buffer += data.toString(); if (this.maxLength && buffer.length > this.maxLength) { cancelled = true; this.logger.warn('Paste exceeds maximum length.'); res.writeHead(400, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Paste exceeds maximum length.' })); } }); req.on('end', () => { if (cancelled) return; if (this.createKey !== '') { if (!buffer.startsWith(this.createKey)) { this.logger.warn('Error adding new paste: wrong key'); res.writeHead(403, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Error adding new paste: wrong key' })); return; } buffer = buffer.substring(this.createKey.length); } this.chooseKey((key) => { this.store.set(key, buffer, (success) => { if (success) { this.logger.verbose(`New paste: ${key}`); res.writeHead(200, { 'content-type': 'application/json' }); res.end(JSON.stringify({ key: key })); } else { this.logger.warn('Error adding new paste.'); res.writeHead(500, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Error adding new paste.' })); } }); }); }); req.on('error', (error) => { this.logger.error(`Connection error: ${error.message}`); res.writeHead(500, { 'content-type': 'application/json' }); res.end(JSON.stringify({ message: 'Connection error.' })); }); } // creates new keys until one is not taken chooseKey(callback) { const key = this.acceptableKey(); this.store.get(key, (success) => { if (success) { this.chooseKey(callback); } else { callback(key); } }); } // creates a new key using the key-generator acceptableKey() { return this.keyGenerator.createKey(this.keyLength); } } module.exports = DocumentHandler;