church_streamer/api/server.mjs

146 lines
4.1 KiB
JavaScript
Raw Permalink Normal View History

2024-02-13 23:54:45 +00:00
import { Flaska, QueryHandler, JsonHandler, HttpError } from 'flaska'
import config from './config.mjs'
import StaticRoutes from './static_routes.mjs'
import ServeHandler from './serve.mjs'
import SocketServer from './io.mjs'
import EncoderRoutes from './encoder/routes.mjs'
import SerialRoutes from './serial/routes.mjs'
import HealthRoutes from './health/routes.mjs'
2024-02-13 23:54:45 +00:00
export default class Server {
constructor(http, port, core, opts = {}) {
Object.assign(this, opts)
Object.assign(this, {
http, port, core,
})
let localUtil = new this.core.sc.Util(import.meta.url)
this.flaskaOptions = {
appendHeaders: {
'Content-Security-Policy': `default-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data: blob:; font-src 'self' data:; object-src 'none'; frame-ancestors 'none'; connect-src 'self' https://media.nfp.is/; media-src 'self' https://cdn.nfp.is/`,
},
nonce: [],
log: this.core.log,
}
this.jsonHandler = JsonHandler
this.routes = {
static: new StaticRoutes(),
encoder: new EncoderRoutes(),
serial: new SerialRoutes(),
health: new HealthRoutes({ version: this.core.version }),
serve: new ServeHandler({
root: localUtil.getPathFromRoot('../public'),
version: this.core.version,
frontend: config.get('frontend:url'),
}),
2024-02-13 23:54:45 +00:00
}
}
runCreateServer() {
// Create our server
this.flaska = new Flaska(this.flaskaOptions, this.http)
// configure our server
if (config.get('NODE_ENV') === 'development') {
this.flaska.devMode()
}
this.flaska.onerror((err, ctx) => {
if (err instanceof HttpError && err.status !== 500) {
ctx.status = err.status
ctx.log.warn(err.message)
} else {
ctx.log.error(err.inner || err)
if (err.extra) {
ctx.log.error({ extra: err.extra }, 'Database parameters')
}
ctx.status = 500
}
ctx.body = {
status: ctx.status,
message: err.message,
}
})
this.flaska.before(function(ctx) {
ctx.state.started = new Date().getTime()
ctx.req.ip = ctx.req.headers['x-forwarded-for'] || ctx.req.connection.remoteAddress
ctx.log = ctx.log.child({
id: Math.random().toString(36).substring(2, 14),
})
ctx.db = this.pool
}.bind(this))
this.flaska.before(QueryHandler())
let healthChecks = 0
let healthCollectLimit = 60 * 60 * 12
this.flaska.after(function(ctx) {
if (ctx.aborted && ctx.status === 200) {
ctx.status = 299
}
let ended = new Date().getTime()
var requestTime = ended - ctx.state.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' || ctx.url === '/api/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
} else if (ctx.url.startsWith('/assets')) {
return
2024-02-13 23:54:45 +00:00
}
ctx.log[level]({
duration: requestTime,
status: ctx.status,
ip: ctx.req.ip,
}, (ctx.aborted ? '[ABORT]' : '<--') + ` ${status}${ctx.method} ${ctx.url}`)
})
}
runRegisterRoutes() {
let keys = Object.keys(this.routes)
for (let key of keys) {
if (this.routes[key].register) {
this.routes[key].register(this)
}
}
}
runCreateSocket() {
this.io = new SocketServer(this.db, this.core.log, this.routes)
this.io.init(this, this.flaska.server)
2024-02-13 23:54:45 +00:00
}
runStartListen() {
return this.flaska.listenAsync(this.port).then(() => {
this.core.log.info('Server is listening on port ' + this.port)
this.runCreateSocket()
})
}
run() {
this.runCreateServer()
this.runRegisterRoutes()
return this.runStartListen()
}
}