2022-04-19 17:42:07 +00:00
|
|
|
import path from 'path'
|
2022-06-16 22:44:43 +00:00
|
|
|
import dot from 'dot'
|
2022-04-19 17:42:07 +00:00
|
|
|
import { FileResponse, HttpError } from 'flaska'
|
|
|
|
import fs from 'fs/promises'
|
2022-06-16 22:44:43 +00:00
|
|
|
import fsSync from 'fs'
|
2022-08-18 09:59:48 +00:00
|
|
|
import { RankLevels, verifyValidToken } from './authentication/security.mjs'
|
2022-06-16 22:44:43 +00:00
|
|
|
|
2022-04-19 17:42:07 +00:00
|
|
|
export default class ServeHandler {
|
|
|
|
constructor(opts = {}) {
|
2022-08-18 09:59:48 +00:00
|
|
|
Object.assign(this, opts)
|
|
|
|
if (!opts.fs) {
|
|
|
|
this.fs = fs
|
|
|
|
}
|
|
|
|
if (!opts.fsSync) {
|
|
|
|
this.fsSync = fsSync
|
|
|
|
}
|
|
|
|
if (!opts.frontend) {
|
|
|
|
this.frontend = 'http://localhost:4000'
|
|
|
|
}
|
|
|
|
if (!opts.version) {
|
|
|
|
this.version = 'version'
|
|
|
|
}
|
2022-06-16 22:44:43 +00:00
|
|
|
|
|
|
|
let indexFile = fsSync.readFileSync(path.join(this.root, 'index.html'))
|
2022-08-22 17:17:39 +00:00
|
|
|
this.template = dot.template(indexFile.toString(), { argName: ['headerDescription', 'headerImage', 'headerTitle', 'headerUrl', 'payloadData', 'payloadTree', 'version', 'nonce', 'type', 'banner', 'media', 'in_debug'] })
|
2022-06-16 22:44:43 +00:00
|
|
|
// console.log(indexFile.toString())
|
2022-04-19 17:42:07 +00:00
|
|
|
}
|
|
|
|
|
2022-08-02 09:34:02 +00:00
|
|
|
register(server) {
|
|
|
|
server.flaska.get('/::file', this.serve.bind(this))
|
|
|
|
}
|
|
|
|
|
2022-04-19 17:42:07 +00:00
|
|
|
/** GET: /::file */
|
|
|
|
serve(ctx) {
|
|
|
|
if (ctx.params.file.startsWith('api/')) {
|
2022-08-18 09:59:48 +00:00
|
|
|
return this.serveIndex(ctx)
|
2022-04-19 17:42:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let file = path.resolve(path.join(this.root, ctx.params.file ? ctx.params.file : 'index.html'))
|
|
|
|
|
2022-08-18 09:59:48 +00:00
|
|
|
if (!ctx.params.file
|
|
|
|
|| ctx.params.file === 'index.html'
|
|
|
|
|| ctx.params.file.startsWith('/page')
|
|
|
|
|| ctx.params.file.startsWith('/article')
|
|
|
|
|| ctx.params.file.startsWith('/admin')) {
|
2022-06-16 22:44:43 +00:00
|
|
|
return this.serveIndex(ctx)
|
|
|
|
}
|
|
|
|
|
2022-04-19 17:42:07 +00:00
|
|
|
if (!file.startsWith(this.root)) {
|
2022-08-18 09:59:48 +00:00
|
|
|
return this.serveIndex(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (file.indexOf('admin') >= 0
|
|
|
|
&& (file.indexOf('.js') >= 0 || file.indexOf('.css') >= 0)) {
|
|
|
|
verifyValidToken((ctx.query.get('token') || '').split('.'), RankLevels.Manager)
|
2022-04-19 17:42:07 +00:00
|
|
|
}
|
|
|
|
|
2022-06-16 22:44:43 +00:00
|
|
|
return this.fs.stat(file)
|
|
|
|
.then(function(stat) {
|
2022-08-18 09:59:48 +00:00
|
|
|
if (file.indexOf('admin') === -1) {
|
|
|
|
ctx.headers['Cache-Control'] = 'max-age=2592000'
|
|
|
|
} else {
|
|
|
|
ctx.headers['Cache-Control'] = 'no-store'
|
|
|
|
}
|
2022-06-16 22:44:43 +00:00
|
|
|
ctx.body = new FileResponse(file, stat)
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
2022-04-19 17:42:07 +00:00
|
|
|
if (err.code === 'ENOENT') {
|
2022-06-16 22:44:43 +00:00
|
|
|
return this.serveIndex(ctx)
|
2022-04-19 17:42:07 +00:00
|
|
|
}
|
|
|
|
return Promise.reject(err)
|
|
|
|
})
|
2022-06-16 22:44:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async serveIndex(ctx) {
|
2022-08-18 09:59:48 +00:00
|
|
|
ctx.body = this.template({})
|
2022-06-16 22:44:43 +00:00
|
|
|
ctx.type = 'text/html; charset=utf-8'
|
|
|
|
}
|
|
|
|
|
|
|
|
serveErrorPage(ctx) {
|
|
|
|
|
2022-04-19 17:42:07 +00:00
|
|
|
}
|
|
|
|
}
|