import { performance } from 'perf_hooks' import { Flaska, QueryHandler, JsonHandler, HttpError } from 'flaska' import TestRoutes from './test/routes.mjs' import MediaRoutes from './media/routes.mjs' import config from './config.mjs' export default class Server { constructor(http, port, core, opts = {}) { Object.assign(this, opts) this.http = http this.port = port this.core = core this.jsonHandler = JsonHandler this.queryHandler = QueryHandler this.flaskOptions = { log: this.core.log, } this.routes = { test: new TestRoutes(), media: new MediaRoutes(), } } run() { // Create our server this.flaska = new Flaska(this.flaskOptions, this.http) // configure our server if (config.get('NODE_ENV') === 'development') { this.flaska.devMode() } this.flaska.before(function(ctx) { ctx.__started = performance.now() ctx.log = ctx.log.child({ ip: ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress, }) }) let healthChecks = 0 let healthCollectLimit = 60 * 60 * 12 this.flaska.after(function(ctx) { let ended = performance.now() - ctx.__started let status = '' let level = 'info' if (ctx.status >= 400) { status = ctx.status + ' ' level = 'warn' } if (ctx.status >= 500) { level = 'error' } if (ctx.url === '/health') { healthChecks++ if (healthChecks >= healthCollectLimit) { ctx.log[level]({ duration: Math.round(ended), status: ctx.status, }, `<-- ${status}${ctx.method} ${ctx.url} {has happened ${healthChecks} times}`) healthChecks = 0 } return } ctx.log[level]({ duration: Math.round(ended), status: ctx.status, }, `<-- ${status}${ctx.method} ${ctx.url}`) }) this.flaska.onerror(function(err, ctx) { if (err.status && err.status >= 400 && err.status < 500) { if (err.body && err.body.request) { ctx.log.warn({ request: err.body.request}, err.message) } else { ctx.log.warn(err.message) } } else { ctx.log.error(err) } ctx.status = err.status || 500 if (err instanceof HttpError) { ctx.body = err.body || { status: ctx.status, message: err.message, } } else { ctx.body = { status: ctx.status, message: err.message, } } }) // Register our routes let keys = Object.keys(this.routes) for (let key of keys) { this.routes[key].register(this) } // Start listening return this.flaska.listenAsync(this.port).then(() => { this.core.log.info({ sites: Object.keys(config.get('sites')) }, `Server is listening on port ${this.port}, uploading to ${config.get('uploadFolder')} for following sites`) }) } }