Explorar o código

Поправки для поддержки reverse-proxy, рефакторинг

Book Pauk %!s(int64=2) %!d(string=hai) anos
pai
achega
409befce5e

+ 5 - 1
client/components/Api/webSocketConnection.js

@@ -1,3 +1,7 @@
 import WebSocketConnection from '../../../server/core/WebSocketConnection';
 
-export default new WebSocketConnection();
+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);

+ 2 - 1
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);
 

+ 7 - 7
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);
                     }
                 }

+ 2 - 2
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);
 };

+ 7 - 71
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();

+ 100 - 0
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));
+};