diff --git a/client/components/Api/webSocketConnection.js b/client/components/Api/webSocketConnection.js index f4c2e47..a644c0c 100644 --- a/client/components/Api/webSocketConnection.js +++ b/client/components/Api/webSocketConnection.js @@ -1,3 +1,7 @@ import WebSocketConnection from '../../../server/core/WebSocketConnection'; -export default new WebSocketConnection(); \ No newline at end of file +const protocol = (window.location.protocol == 'https:' ? 'wss:' : 'ws:'); +let url = `${protocol}//${window.location.host}${window.location.pathname}`; +url += (url[url.length - 1] === '/' ? 'ws' : '/ws'); + +export default new WebSocketConnection(url); \ No newline at end of file diff --git a/server/core/RemoteLib.js b/server/core/RemoteLib.js index 2a8d2a4..eea28b3 100644 --- a/server/core/RemoteLib.js +++ b/server/core/RemoteLib.js @@ -68,7 +68,8 @@ class RemoteLib { const buf = await this.down.load(`${this.remoteHost}${link}`, {decompress: false}); - const publicPath = `${this.config.publicFilesDir}${link}`; + const hash = path.basename(link); + const publicPath = `${this.config.bookDir}/${hash}`; await fs.writeFile(publicPath, buf); diff --git a/server/core/WebWorker.js b/server/core/WebWorker.js index 7ce88ad..b8d7a01 100644 --- a/server/core/WebWorker.js +++ b/server/core/WebWorker.js @@ -60,7 +60,7 @@ class WebWorker { const dirConfig = [ { - dir: config.filesDir, + dir: config.bookDir, maxSize: config.maxFilesDirSize, }, ]; @@ -380,8 +380,8 @@ class WebWorker { hash = await this.remoteLib.downloadBook(bookUid); } - const link = `${this.config.filesPathStatic}/${hash}`; - const bookFile = `${this.config.filesDir}/${hash}`; + const link = `${this.config.bookPathStatic}/${hash}`; + const bookFile = `${this.config.bookDir}/${hash}`; const bookFileDesc = `${bookFile}.d.json`; if (!await fs.pathExists(bookFile) || !await fs.pathExists(bookFileDesc)) { @@ -447,11 +447,11 @@ class WebWorker { rows = await db.select({table: 'file_hash', where: `@@id(${db.esc(bookPath)})`}); if (rows.length) {//хеш найден по bookPath const hash = rows[0].hash; - const bookFile = `${this.config.filesDir}/${hash}`; + const bookFile = `${this.config.bookDir}/${hash}`; const bookFileDesc = `${bookFile}.d.json`; if (await fs.pathExists(bookFile) && await fs.pathExists(bookFileDesc)) { - link = `${this.config.filesPathStatic}/${hash}`; + link = `${this.config.bookPathStatic}/${hash}`; } } @@ -479,7 +479,7 @@ class WebWorker { let bookInfo = await this.getBookLink(bookUid); const hash = path.basename(bookInfo.link); - const bookFile = `${this.config.filesDir}/${hash}`; + const bookFile = `${this.config.bookDir}/${hash}`; const bookFileInfo = `${bookFile}.i.json`; let rows = await db.select({table: 'book', where: `@@hash('_uid', ${db.esc(bookUid)})`}); @@ -501,7 +501,7 @@ class WebWorker { result.fb2 = fb2.rawNodes; if (cover) { - result.cover = `${this.config.filesPathStatic}/${hash}${coverExt}`; + result.cover = `${this.config.bookPathStatic}/${hash}${coverExt}`; await fs.writeFile(`${bookFile}${coverExt}`, cover); } } diff --git a/server/createWebApp.js b/server/createWebApp.js index cc3c85b..f292954 100644 --- a/server/createWebApp.js +++ b/server/createWebApp.js @@ -9,7 +9,7 @@ module.exports = async(config) => { if (await fs.pathExists(verFile)) { const curPublicVersion = await fs.readFile(verFile, 'utf8'); - if (curPublicVersion == config.version) + if (curPublicVersion == config.version + config.rootPathStatic) return; } @@ -26,6 +26,6 @@ module.exports = async(config) => { await zipReader.close(); } - await fs.writeFile(verFile, config.version); + await fs.writeFile(verFile, config.version + config.rootPathStatic); await fs.remove(zipFile); }; \ No newline at end of file diff --git a/server/index.js b/server/index.js index 673e265..3d9aa66 100644 --- a/server/index.js +++ b/server/index.js @@ -50,13 +50,14 @@ async function init() { config.logDir = `${config.dataDir}/log`; config.publicDir = `${config.dataDir}/public`; config.publicFilesDir = `${config.dataDir}/public-files`; - config.filesPathStatic = `/book`; - config.filesDir = `${config.publicFilesDir}${config.filesPathStatic}`; + config.rootPathStatic = `/root`; + config.bookPathStatic = `${config.rootPathStatic}/book`; + config.bookDir = `${config.publicFilesDir}/book`; configManager.config = config; await fs.ensureDir(config.dataDir); - await fs.ensureDir(config.filesDir); + await fs.ensureDir(config.bookDir); await fs.ensureDir(config.tempDir); await fs.emptyDir(config.tempDir); @@ -148,7 +149,7 @@ async function main() { if (branch == 'development') { const devFileName = './dev.js'; //require ignored by pkg -50Mb executable size devModule = require(devFileName); - devModule.webpackDevMiddleware(app); + //devModule.webpackDevMiddleware(app); } if (devModule) @@ -156,6 +157,8 @@ async function main() { const opds = require('./core/opds'); opds(app, config); + + const initStatic = require('./static'); initStatic(app, config); const webAccess = new (require('./core/WebAccess'))(config); @@ -179,73 +182,6 @@ async function main() { }); } -function initStatic(app, config) { - /* - publicFilesDir = `${config.dataDir}/public-files`; - filesPathStatic = `/book`; - filesDir = `${config.publicFilesDir}${config.filesPathStatic}`; - */ - //загрузка или восстановление файлов в /files, при необходимости - app.use(config.filesPathStatic, async(req, res, next) => { - if (req.method !== 'GET' && req.method !== 'HEAD') { - return next(); - } - - if (path.extname(req.path) == '') { - const bookFile = `${config.filesDir}${req.path}`; - const bookFileDesc = `${bookFile}.d.json`; - - let downFileName = ''; - //восстановим из json-файла описания - try { - if (await fs.pathExists(bookFile) && await fs.pathExists(bookFileDesc)) { - await utils.touchFile(bookFile); - await utils.touchFile(bookFileDesc); - - let desc = await fs.readFile(bookFileDesc, 'utf8'); - desc = JSON.parse(desc); - downFileName = desc.downFileName; - } else { - await fs.remove(bookFile); - await fs.remove(bookFileDesc); - } - } catch(e) { - log(LM_ERR, e.message); - } - - if (downFileName) { - res.downFileName = downFileName; - - if (!req.acceptsEncodings('gzip')) { - //не принимает gzip, тогда распакуем - const rawFile = `${bookFile}.raw`; - if (!await fs.pathExists(rawFile)) - await utils.gunzipFile(bookFile, rawFile); - - req.url += '.raw'; - res.rawFile = true; - } - } - } - - return next(); - }); - - //заголовки при отдаче - app.use(config.filesPathStatic, express.static(config.filesDir, { - setHeaders: (res) => { - if (res.downFileName) { - if (!res.rawFile) - res.set('Content-Encoding', 'gzip'); - - res.set('Content-Disposition', `inline; filename*=UTF-8''${encodeURIComponent(res.downFileName)}`); - } - }, - })); - - app.use(express.static(config.publicDir)); -} - (async() => { try { await init(); diff --git a/server/static.js b/server/static.js new file mode 100644 index 0000000..c27926f --- /dev/null +++ b/server/static.js @@ -0,0 +1,100 @@ +const fs = require('fs-extra'); +const path = require('path'); + +const express = require('express'); +const utils = require('./core/utils'); +const webAppDir = require('../build/appdir'); + +const log = new (require('./core/AppLogger'))().log;//singleton + +module.exports = (app, config) => { + /* + config.bookPathStatic = `${config.rootPathStatic}/book`; + config.bookDir = `${config.publicFilesDir}/book`; + */ + //загрузка или восстановление файлов в /public-files, при необходимости + app.use(config.bookPathStatic, async(req, res, next) => { + if (req.method !== 'GET' && req.method !== 'HEAD') { + return next(); + } + + if (path.extname(req.path) == '') { + const bookFile = `${config.bookDir}${req.path}`; + const bookFileDesc = `${bookFile}.d.json`; + + let downFileName = ''; + //восстановим из json-файла описания + try { + if (await fs.pathExists(bookFile) && await fs.pathExists(bookFileDesc)) { + await utils.touchFile(bookFile); + await utils.touchFile(bookFileDesc); + + let desc = await fs.readFile(bookFileDesc, 'utf8'); + desc = JSON.parse(desc); + downFileName = desc.downFileName; + } else { + await fs.remove(bookFile); + await fs.remove(bookFileDesc); + } + } catch(e) { + log(LM_ERR, e.message); + } + + if (downFileName) { + res.downFileName = downFileName; + + if (!req.acceptsEncodings('gzip')) { + //не принимает gzip, тогда распакуем + const rawFile = `${bookFile}.raw`; + if (!await fs.pathExists(rawFile)) + await utils.gunzipFile(bookFile, rawFile); + + req.url += '.raw'; + res.rawFile = true; + } + } + } + + return next(); + }); + + //заголовки при отдаче + app.use(config.bookPathStatic, express.static(config.bookDir, { + setHeaders: (res) => { + if (res.downFileName) { + if (!res.rawFile) + res.set('Content-Encoding', 'gzip'); + + res.set('Content-Disposition', `inline; filename*=UTF-8''${encodeURIComponent(res.downFileName)}`); + } + }, + })); + + if (config.rootPathStatic) { + //подмена rootPath в файлах статики WebApp при необходимости + app.use(config.rootPathStatic, async(req, res, next) => { + if (req.method !== 'GET' && req.method !== 'HEAD') { + return next(); + } + + const reqPath = (req.path == '/' ? '/index.html' : req.path); + const ext = path.extname(reqPath); + if (ext == '.html' || ext == '.js' || ext == '.css') { + const reqFile = `${config.publicDir}${reqPath}`; + const flagFile = `${reqFile}.replaced`; + + if (!await fs.pathExists(flagFile) && await fs.pathExists(reqFile)) { + const content = await fs.readFile(reqFile, 'utf8'); + const re = new RegExp(`/${webAppDir}`, 'g'); + await fs.writeFile(reqFile, content.replace(re, `${config.rootPathStatic}/${webAppDir}`)); + await fs.writeFile(flagFile, ''); + } + } + + return next(); + }); + } + + //статика файлов WebApp + app.use(config.rootPathStatic, express.static(config.publicDir)); +}; \ No newline at end of file