From 7268d24143dca10b75b64a6800cec9fdfa4e1d72 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Sun, 16 Sep 2018 00:55:30 -0300 Subject: Base structures --- src/api/structures/Server.js | 78 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/api/structures/Server.js (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js new file mode 100644 index 0000000..ae4b678 --- /dev/null +++ b/src/api/structures/Server.js @@ -0,0 +1,78 @@ +const config = require('../../../config'); +const log = require('../utils/Log'); +const express = require('express'); +const helmet = require('helmet'); +const cors = require('cors'); +const RateLimit = require('express-rate-limit'); +const bodyParser = require('body-parser'); +const jetpack = require('fs-jetpack'); +const path = require('path'); +const Database = require('./Database'); +const oneliner = require('one-liner'); + +const rateLimiter = new RateLimit({ + windowMs: config.server.rateLimits.window, + max: config.server.rateLimits.max, + delayMs: 0 +}); + +class Server { + constructor() { + this.port = config.server.ports.backend; + this.server = express(); + this.server.set('trust proxy', 1); + this.server.use(helmet()); + this.server.use(cors({ allowedHeaders: ['Accept', 'Authorization', 'Cache-Control', 'X-Requested-With', 'Content-Type', 'albumId'] })); + this.server.use((req, res, next) => { + if (req.headers.accept === 'application/vnd.lolisafe.json') return next(); + return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); + }); + this.server.use(bodyParser.urlencoded({ extended: true })); + this.server.use(bodyParser.json()); + // this.server.use(rateLimiter); + this.routesFolder = path.join(__dirname, '..', 'routes'); + this.database = new Database(); + this.server.get('/config', (req, res) => res.json({ + baseURL: config.backendLocation, + serviceName: config.serviceName, + maxFileSize: config.uploads.uploadMaxSize, + chunkSize: config.uploads.chunkSize + })); + } + + registerAllTheRoutes() { + jetpack.find(this.routesFolder, { matching: '*.js' }).forEach(routeFile => { + const RouteClass = require(path.join('..', '..', '..', routeFile)); + let routes = [RouteClass]; + if (Array.isArray(RouteClass)) routes = RouteClass; + for (const File of routes) { + const route = new File(); + this.server[route.method](config.server.routePrefix + route.path, route.authorize.bind(route)); + log.info(`Found route ${route.method.toUpperCase()} ${config.server.routePrefix}${route.path}`); + } + }); + } + + writeFrontendConfig() { + const template = oneliner` + module.exports = { + baseURL: '${config.backendLocation}', + serviceName: '${config.serviceName}', + maxFileSize: '${config.uploads.uploadMaxSize}', + chunkSize: '${config.uploads.chunkSize}' + }`; + jetpack.write(path.join(__dirname, '..', '..', 'frontend', 'config.js'), template); + log.success('Frontend config file generated successfully'); + } + + start() { + jetpack.dir('uploads/chunks'); + jetpack.dir('uploads/thumbs/square'); + this.registerAllTheRoutes(); + this.server.listen(this.port, () => { + log.success(`Backend ready and listening on port ${this.port}`); + }); + } +} + +module.exports = Server; -- cgit v1.2.3 From 4b2b02110b457d8ebeee78e1bdf99eb0660d0626 Mon Sep 17 00:00:00 2001 From: Pitu <7425261+Pitu@users.noreply.github.com> Date: Tue, 18 Sep 2018 03:34:00 -0300 Subject: We can now download albums yayyyy --- src/api/structures/Server.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index ae4b678..0b05570 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -24,6 +24,10 @@ class Server { this.server.use(helmet()); this.server.use(cors({ allowedHeaders: ['Accept', 'Authorization', 'Cache-Control', 'X-Requested-With', 'Content-Type', 'albumId'] })); this.server.use((req, res, next) => { + /* + This bypasses the headers.accept for album download, since it's accesed directly through the browser. + */ + if (req.url.includes('/api/album/') && req.url.includes('/zip') && req.method === 'GET') return next(); if (req.headers.accept === 'application/vnd.lolisafe.json') return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); -- cgit v1.2.3 From e33cf304495d327b152a01cc6906643ccd8dd62a Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 19 Feb 2019 00:06:38 +0900 Subject: Changes --- src/api/structures/Server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 0b05570..5ead078 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -79,4 +79,4 @@ class Server { } } -module.exports = Server; +new Server().start(); -- cgit v1.2.3 From 89a271818ed25b0a17a17dd1d6804e34d1f2ec0f Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 19 Feb 2019 23:52:24 +0900 Subject: Switch config to .env --- src/api/structures/Server.js | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 5ead078..dc72558 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -1,4 +1,5 @@ -const config = require('../../../config'); +require('dotenv').config(); + const log = require('../utils/Log'); const express = require('express'); const helmet = require('helmet'); @@ -8,17 +9,16 @@ const bodyParser = require('body-parser'); const jetpack = require('fs-jetpack'); const path = require('path'); const Database = require('./Database'); -const oneliner = require('one-liner'); const rateLimiter = new RateLimit({ - windowMs: config.server.rateLimits.window, - max: config.server.rateLimits.max, + windowMs: process.env.RATE_LIMIT_WINDOW, + max: process.env.RATE_LIMIT_MAX, delayMs: 0 }); class Server { constructor() { - this.port = config.server.ports.backend; + this.port = process.env.SERVER_PORT; this.server = express(); this.server.set('trust proxy', 1); this.server.use(helmet()); @@ -36,12 +36,6 @@ class Server { // this.server.use(rateLimiter); this.routesFolder = path.join(__dirname, '..', 'routes'); this.database = new Database(); - this.server.get('/config', (req, res) => res.json({ - baseURL: config.backendLocation, - serviceName: config.serviceName, - maxFileSize: config.uploads.uploadMaxSize, - chunkSize: config.uploads.chunkSize - })); } registerAllTheRoutes() { @@ -51,24 +45,12 @@ class Server { if (Array.isArray(RouteClass)) routes = RouteClass; for (const File of routes) { const route = new File(); - this.server[route.method](config.server.routePrefix + route.path, route.authorize.bind(route)); - log.info(`Found route ${route.method.toUpperCase()} ${config.server.routePrefix}${route.path}`); + this.server[route.method](process.env.ROUTE_PREFIX + route.path, route.authorize.bind(route)); + log.info(`Found route ${route.method.toUpperCase()} ${process.env.ROUTE_PREFIX}${route.path}`); } }); } - writeFrontendConfig() { - const template = oneliner` - module.exports = { - baseURL: '${config.backendLocation}', - serviceName: '${config.serviceName}', - maxFileSize: '${config.uploads.uploadMaxSize}', - chunkSize: '${config.uploads.chunkSize}' - }`; - jetpack.write(path.join(__dirname, '..', '..', 'frontend', 'config.js'), template); - log.success('Frontend config file generated successfully'); - } - start() { jetpack.dir('uploads/chunks'); jetpack.dir('uploads/thumbs/square'); -- cgit v1.2.3 From 44e6fd31d2fa7761c90ff1d6932cf69d163b22e8 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 21 Feb 2019 23:49:29 +0900 Subject: Database migration and seeding --- src/api/structures/Server.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index dc72558..d2cc2f1 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -8,7 +8,6 @@ const RateLimit = require('express-rate-limit'); const bodyParser = require('body-parser'); const jetpack = require('fs-jetpack'); const path = require('path'); -const Database = require('./Database'); const rateLimiter = new RateLimit({ windowMs: process.env.RATE_LIMIT_WINDOW, @@ -35,7 +34,6 @@ class Server { this.server.use(bodyParser.json()); // this.server.use(rateLimiter); this.routesFolder = path.join(__dirname, '..', 'routes'); - this.database = new Database(); } registerAllTheRoutes() { -- cgit v1.2.3 From 73d85e8c7938e1db30da3cc4354b143d4a078473 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 2 Mar 2019 02:08:11 +0900 Subject: Enviroment variables parsing fix --- src/api/structures/Server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index d2cc2f1..0dd22d7 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -10,14 +10,14 @@ const jetpack = require('fs-jetpack'); const path = require('path'); const rateLimiter = new RateLimit({ - windowMs: process.env.RATE_LIMIT_WINDOW, - max: process.env.RATE_LIMIT_MAX, + windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10), + max: parseInt(process.env.RATE_LIMIT_MAX, 10), delayMs: 0 }); class Server { constructor() { - this.port = process.env.SERVER_PORT; + this.port = parseInt(process.env.SERVER_PORT, 10); this.server = express(); this.server.set('trust proxy', 1); this.server.use(helmet()); -- cgit v1.2.3 From 9aba5cd2216b7daf48850f430919db69f4925713 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 29 Mar 2019 00:36:39 +0900 Subject: Fix --- src/api/structures/Server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 0dd22d7..d10abc9 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -27,7 +27,7 @@ class Server { This bypasses the headers.accept for album download, since it's accesed directly through the browser. */ if (req.url.includes('/api/album/') && req.url.includes('/zip') && req.method === 'GET') return next(); - if (req.headers.accept === 'application/vnd.lolisafe.json') return next(); + if (req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); this.server.use(bodyParser.urlencoded({ extended: true })); -- cgit v1.2.3 From 5dc7eda038d673767fbb0f872632695b42a21304 Mon Sep 17 00:00:00 2001 From: Pitu Date: Tue, 16 Apr 2019 02:56:49 +0000 Subject: Check if accept header is passed --- src/api/structures/Server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index d10abc9..f8c6ad1 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -27,7 +27,7 @@ class Server { This bypasses the headers.accept for album download, since it's accesed directly through the browser. */ if (req.url.includes('/api/album/') && req.url.includes('/zip') && req.method === 'GET') return next(); - if (req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); + if (req.headers.accept && req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); this.server.use(bodyParser.urlencoded({ extended: true })); -- cgit v1.2.3 From 8e4f1b7838e3c43320f2e25e691c1808ae3c4089 Mon Sep 17 00:00:00 2001 From: Pitu Date: Mon, 30 Sep 2019 07:06:22 +0000 Subject: feature: album links --- src/api/structures/Server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index f8c6ad1..50f6754 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -26,7 +26,7 @@ class Server { /* This bypasses the headers.accept for album download, since it's accesed directly through the browser. */ - if (req.url.includes('/api/album/') && req.url.includes('/zip') && req.method === 'GET') return next(); + if ((req.url.includes('/api/album/') || req.url.includes('/zip')) && req.method === 'GET') return next(); if (req.headers.accept && req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); -- cgit v1.2.3 From c114e59be329fa9ceb8f1f8e79356a0e3afbd1ae Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 9 May 2020 19:21:20 +0900 Subject: Feature: * Frontend is now served by the API process * Only 1 process spawns for lolisafe to work * Switched frontend from server-side render to static site, now saved in `/dist` --- src/api/structures/Server.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 50f6754..c80c44f 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -23,16 +23,23 @@ class Server { this.server.use(helmet()); this.server.use(cors({ allowedHeaders: ['Accept', 'Authorization', 'Cache-Control', 'X-Requested-With', 'Content-Type', 'albumId'] })); this.server.use((req, res, next) => { - /* - This bypasses the headers.accept for album download, since it's accesed directly through the browser. - */ + // This bypasses the headers.accept for album download, since it's accesed directly through the browser. if ((req.url.includes('/api/album/') || req.url.includes('/zip')) && req.method === 'GET') return next(); + // This bypasses the headers.accept if we are accessing the frontend + if (!req.url.includes('/api/') && req.method === 'GET') return next(); if (req.headers.accept && req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); this.server.use(bodyParser.urlencoded({ extended: true })); this.server.use(bodyParser.json()); // this.server.use(rateLimiter); + + // Serve the frontend if we are in production mode + if (process.env.NODE_ENV === 'production') { + this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist'))); + this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads'))); + } + this.routesFolder = path.join(__dirname, '..', 'routes'); } -- cgit v1.2.3 From 4c52932426a3e91a205940a6ab08bfee3e23fadf Mon Sep 17 00:00:00 2001 From: Pitu Date: Sun, 10 May 2020 20:02:48 +0900 Subject: Features: * Serve files during development * Own endpoint for fetching the albums of a file --- src/api/structures/Server.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index c80c44f..44d4e44 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -37,8 +37,9 @@ class Server { // Serve the frontend if we are in production mode if (process.env.NODE_ENV === 'production') { this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist'))); - this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads'))); } + // Serve the uploads + this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads'))); this.routesFolder = path.join(__dirname, '..', 'routes'); } -- cgit v1.2.3 From 207fc916d960b04190f7a971d672000fbd934baf Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 25 Jun 2020 02:06:11 +0900 Subject: Handle nuxt routes on page load --- src/api/structures/Server.js | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 44d4e44..a8eccd9 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -34,13 +34,8 @@ class Server { this.server.use(bodyParser.json()); // this.server.use(rateLimiter); - // Serve the frontend if we are in production mode - if (process.env.NODE_ENV === 'production') { - this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist'))); - } // Serve the uploads this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads'))); - this.routesFolder = path.join(__dirname, '..', 'routes'); } @@ -57,10 +52,32 @@ class Server { }); } + serveNuxt() { + // Serve the frontend if we are in production mode + if (process.env.NODE_ENV === 'production') { + this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist'))); + } + + /* + For vue router to work with express we need this fallback. + After all the routes are loaded and the static files handled and if the + user is trying to access a non-mapped route we serve the website instead + since it has routes of it's own that don't work if accessed directly + */ + this.server.all('*', (_req, res) => { + try { + res.sendFile(path.join(__dirname, '..', '..', '..', 'dist', 'index.html')); + } catch (error) { + res.json({ success: false, message: 'Something went wrong' }); + } + }); + } + start() { jetpack.dir('uploads/chunks'); jetpack.dir('uploads/thumbs/square'); this.registerAllTheRoutes(); + this.serveNuxt(); this.server.listen(this.port, () => { log.success(`Backend ready and listening on port ${this.port}`); }); -- cgit v1.2.3 From 49d3e3b203ee287a53beb2a04faa8bf38ace6834 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 03:15:27 +0300 Subject: feat: add morgan for logging requests if env is not production --- src/api/structures/Server.js | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index a8eccd9..5d2290b 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -1,6 +1,5 @@ require('dotenv').config(); -const log = require('../utils/Log'); const express = require('express'); const helmet = require('helmet'); const cors = require('cors'); @@ -8,11 +7,14 @@ const RateLimit = require('express-rate-limit'); const bodyParser = require('body-parser'); const jetpack = require('fs-jetpack'); const path = require('path'); +const morgan = require('morgan'); +const log = require('../utils/Log'); +const ThumbUtil = require('../utils/ThumbUtil'); const rateLimiter = new RateLimit({ windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10), max: parseInt(process.env.RATE_LIMIT_MAX, 10), - delayMs: 0 + delayMs: 0, }); class Server { @@ -32,16 +34,38 @@ class Server { }); this.server.use(bodyParser.urlencoded({ extended: true })); this.server.use(bodyParser.json()); + if (process.env.NODE_ENV !== 'production') { + this.server.use(morgan('combined', { + skip(req) { + let ext = req.path.split('.').pop(); + if (ext) { ext = `.${ext.toLowerCase()}`; } + + if ( + ThumbUtil.imageExtensions.indexOf(ext) > -1 + || ThumbUtil.videoExtensions.indexOf(ext) > -1 + || req.path.indexOf('_nuxt') > -1 + || req.path.indexOf('favicon.ico') > -1 + ) { + return true; + } + return false; + }, + 'stream': { + write(str) { log.debug(str); }, + }, + })); + } // this.server.use(rateLimiter); // Serve the uploads - this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads'))); - this.routesFolder = path.join(__dirname, '..', 'routes'); + this.server.use(express.static(path.join(__dirname, '../../../uploads'))); + this.routesFolder = path.join(__dirname, '../routes'); } registerAllTheRoutes() { - jetpack.find(this.routesFolder, { matching: '*.js' }).forEach(routeFile => { - const RouteClass = require(path.join('..', '..', '..', routeFile)); + jetpack.find(this.routesFolder, { matching: '*.js' }).forEach((routeFile) => { + // eslint-disable-next-line import/no-dynamic-require, global-require + const RouteClass = require(path.join('../../../', routeFile)); let routes = [RouteClass]; if (Array.isArray(RouteClass)) routes = RouteClass; for (const File of routes) { @@ -55,7 +79,7 @@ class Server { serveNuxt() { // Serve the frontend if we are in production mode if (process.env.NODE_ENV === 'production') { - this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist'))); + this.server.use(express.static(path.join(__dirname, '../../../dist'))); } /* @@ -66,7 +90,7 @@ class Server { */ this.server.all('*', (_req, res) => { try { - res.sendFile(path.join(__dirname, '..', '..', '..', 'dist', 'index.html')); + res.sendFile(path.join(__dirname, '../../../dist/index.html')); } catch (error) { res.json({ success: false, message: 'Something went wrong' }); } -- cgit v1.2.3 From ad852de51a0d2dd5d29c08838d5a430c58849e74 Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Wed, 8 Jul 2020 04:00:12 +0300 Subject: chore: linter the entire project using the new rules --- src/api/structures/Server.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 5d2290b..c8537fb 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -11,6 +11,7 @@ const morgan = require('morgan'); const log = require('../utils/Log'); const ThumbUtil = require('../utils/ThumbUtil'); +// eslint-disable-next-line no-unused-vars const rateLimiter = new RateLimit({ windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10), max: parseInt(process.env.RATE_LIMIT_MAX, 10), -- cgit v1.2.3 From 2d06d918a154c15196ca92fb8f7873ca3c797f00 Mon Sep 17 00:00:00 2001 From: Pitu Date: Sat, 18 Jul 2020 02:21:31 +0900 Subject: Timeout, package and docs cleanup --- src/api/structures/Server.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index a8eccd9..2039ed5 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -78,9 +78,10 @@ class Server { jetpack.dir('uploads/thumbs/square'); this.registerAllTheRoutes(); this.serveNuxt(); - this.server.listen(this.port, () => { + const server = this.server.listen(this.port, () => { log.success(`Backend ready and listening on port ${this.port}`); }); + server.setTimeout(600000); } } -- cgit v1.2.3 From 6fee07d9e15fb785721d9c6870231f1d0c95f10c Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Mon, 20 Jul 2020 21:29:06 +0300 Subject: fix: don't crash the server if a route fails to load --- src/api/structures/Server.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 7f1b4d5..e25e089 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -70,9 +70,13 @@ class Server { let routes = [RouteClass]; if (Array.isArray(RouteClass)) routes = RouteClass; for (const File of routes) { - const route = new File(); - this.server[route.method](process.env.ROUTE_PREFIX + route.path, route.authorize.bind(route)); - log.info(`Found route ${route.method.toUpperCase()} ${process.env.ROUTE_PREFIX}${route.path}`); + try { + const route = new File(); + this.server[route.method](process.env.ROUTE_PREFIX + route.path, route.authorize.bind(route)); + log.info(`Found route ${route.method.toUpperCase()} ${process.env.ROUTE_PREFIX}${route.path}`); + } catch (e) { + log.error(`Failed loading route from file ${routeFile} with error: ${e.message}`); + } } }); } -- cgit v1.2.3 From 90001c2df56d58e69fd199a518ae7f3e4ed327fc Mon Sep 17 00:00:00 2001 From: Zephyrrus Date: Thu, 24 Dec 2020 10:40:50 +0200 Subject: chore: remove trailing commas --- src/api/structures/Server.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index e25e089..83b2880 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -15,7 +15,7 @@ const ThumbUtil = require('../utils/ThumbUtil'); const rateLimiter = new RateLimit({ windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10), max: parseInt(process.env.RATE_LIMIT_MAX, 10), - delayMs: 0, + delayMs: 0 }); class Server { @@ -52,8 +52,8 @@ class Server { return false; }, 'stream': { - write(str) { log.debug(str); }, - }, + write(str) { log.debug(str); } + } })); } // this.server.use(rateLimiter); -- cgit v1.2.3 From fb2c27086f570fec60f4d52dcc9ca80e53186293 Mon Sep 17 00:00:00 2001 From: Pitu Date: Thu, 24 Dec 2020 23:45:16 +0900 Subject: Fix ESLint rules once and for all --- src/api/structures/Server.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 83b2880..0ef91fd 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -42,16 +42,16 @@ class Server { if (ext) { ext = `.${ext.toLowerCase()}`; } if ( - ThumbUtil.imageExtensions.indexOf(ext) > -1 - || ThumbUtil.videoExtensions.indexOf(ext) > -1 - || req.path.indexOf('_nuxt') > -1 - || req.path.indexOf('favicon.ico') > -1 + ThumbUtil.imageExtensions.indexOf(ext) > -1 || + ThumbUtil.videoExtensions.indexOf(ext) > -1 || + req.path.indexOf('_nuxt') > -1 || + req.path.indexOf('favicon.ico') > -1 ) { return true; } return false; }, - 'stream': { + stream: { write(str) { log.debug(str); } } })); @@ -64,7 +64,7 @@ class Server { } registerAllTheRoutes() { - jetpack.find(this.routesFolder, { matching: '*.js' }).forEach((routeFile) => { + jetpack.find(this.routesFolder, { matching: '*.js' }).forEach(routeFile => { // eslint-disable-next-line import/no-dynamic-require, global-require const RouteClass = require(path.join('../../../', routeFile)); let routes = [RouteClass]; -- cgit v1.2.3 From 09d8d02e6c11bb4aea9cd129bf195868bab0738f Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 02:08:54 +0900 Subject: Cleanup --- src/api/structures/Server.js | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 0ef91fd..6a4abaa 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -7,9 +7,7 @@ const RateLimit = require('express-rate-limit'); const bodyParser = require('body-parser'); const jetpack = require('fs-jetpack'); const path = require('path'); -const morgan = require('morgan'); const log = require('../utils/Log'); -const ThumbUtil = require('../utils/ThumbUtil'); // eslint-disable-next-line no-unused-vars const rateLimiter = new RateLimit({ @@ -35,27 +33,6 @@ class Server { }); this.server.use(bodyParser.urlencoded({ extended: true })); this.server.use(bodyParser.json()); - if (process.env.NODE_ENV !== 'production') { - this.server.use(morgan('combined', { - skip(req) { - let ext = req.path.split('.').pop(); - if (ext) { ext = `.${ext.toLowerCase()}`; } - - if ( - ThumbUtil.imageExtensions.indexOf(ext) > -1 || - ThumbUtil.videoExtensions.indexOf(ext) > -1 || - req.path.indexOf('_nuxt') > -1 || - req.path.indexOf('favicon.ico') > -1 - ) { - return true; - } - return false; - }, - stream: { - write(str) { log.debug(str); } - } - })); - } // this.server.use(rateLimiter); // Serve the uploads -- cgit v1.2.3 From 3051fbe9480f367be93bdcca45104be7b7d69bd8 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 02:54:05 +0900 Subject: Feat: add rotating logs when running in production env --- src/api/structures/Server.js | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 6a4abaa..cf2a781 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -7,6 +7,8 @@ const RateLimit = require('express-rate-limit'); const bodyParser = require('body-parser'); const jetpack = require('fs-jetpack'); const path = require('path'); +const morgan = require('morgan'); +const rfs = require('rotating-file-stream'); const log = require('../utils/Log'); // eslint-disable-next-line no-unused-vars @@ -33,6 +35,14 @@ class Server { }); this.server.use(bodyParser.urlencoded({ extended: true })); this.server.use(bodyParser.json()); + + if (process.env.NODE_ENV === 'production') { + const accessLogStream = rfs.createStream('access.log', { + interval: '1d', // rotate daily + path: path.join(__dirname, '../../../logs', 'log') + }); + this.server.use(morgan('combined', { stream: accessLogStream })); + } // this.server.use(rateLimiter); // Serve the uploads -- cgit v1.2.3 From 493e05df27ba3b2c6fbd36547f0c7aa1699e038c Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 03:08:53 +0900 Subject: Fix: thumbnail creation --- src/api/structures/Server.js | 1 + 1 file changed, 1 insertion(+) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index cf2a781..865419d 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -92,6 +92,7 @@ class Server { start() { jetpack.dir('uploads/chunks'); jetpack.dir('uploads/thumbs/square'); + jetpack.dir('uploads/thumbs/preview'); this.registerAllTheRoutes(); this.serveNuxt(); const server = this.server.listen(this.port, () => { -- cgit v1.2.3 From 5c2f6782ddeafec5503e5b7187420afc503cd865 Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 20:09:17 +0900 Subject: Chore: prevent server from starting if .env config missing --- src/api/structures/Server.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index 865419d..cc1064f 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -1,5 +1,10 @@ require('dotenv').config(); +if (!process.env.SERVER_PORT) { + console.log('Run the setup script first or fill the .env file manually before starting'); + process.exit(0); +} + const express = require('express'); const helmet = require('helmet'); const cors = require('cors'); @@ -43,7 +48,9 @@ class Server { }); this.server.use(morgan('combined', { stream: accessLogStream })); } - // this.server.use(rateLimiter); + + // Apply rate limiting to the api only + this.server.use('/api/', rateLimiter); // Serve the uploads this.server.use(express.static(path.join(__dirname, '../../../uploads'))); @@ -52,7 +59,6 @@ class Server { registerAllTheRoutes() { jetpack.find(this.routesFolder, { matching: '*.js' }).forEach(routeFile => { - // eslint-disable-next-line import/no-dynamic-require, global-require const RouteClass = require(path.join('../../../', routeFile)); let routes = [RouteClass]; if (Array.isArray(RouteClass)) routes = RouteClass; -- cgit v1.2.3 From ec2f9e0d989792c1760b48e063467cf6e59c580a Mon Sep 17 00:00:00 2001 From: Pitu Date: Fri, 25 Dec 2020 20:45:22 +0900 Subject: Rebrand --- src/api/structures/Server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/api/structures/Server.js') diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js index cc1064f..b8952a9 100644 --- a/src/api/structures/Server.js +++ b/src/api/structures/Server.js @@ -35,7 +35,7 @@ class Server { if ((req.url.includes('/api/album/') || req.url.includes('/zip')) && req.method === 'GET') return next(); // This bypasses the headers.accept if we are accessing the frontend if (!req.url.includes('/api/') && req.method === 'GET') return next(); - if (req.headers.accept && req.headers.accept.includes('application/vnd.lolisafe.json')) return next(); + if (req.headers.accept && req.headers.accept.includes('application/vnd.chibisafe.json')) return next(); return res.status(405).json({ message: 'Incorrect `Accept` header provided' }); }); this.server.use(bodyParser.urlencoded({ extended: true })); -- cgit v1.2.3