routes.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. const fs = require('fs-extra');
  2. const path = require('path');
  3. const express = require('express');
  4. const multer = require('multer');
  5. const ReaderWorker = require('./core/Reader/ReaderWorker');//singleton
  6. const log = new (require('./core/AppLogger'))().log;//singleton
  7. const c = require('./controllers');
  8. const utils = require('./core/utils');
  9. function initRoutes(app, wss, config) {
  10. //эксклюзив для update_checker
  11. if (config.mode === 'book_update_checker') {
  12. new c.BookUpdateCheckerController(wss, config);
  13. return;
  14. }
  15. initStatic(app, config);
  16. const misc = new c.MiscController(config);
  17. const reader = new c.ReaderController(config);
  18. const worker = new c.WorkerController(config);
  19. new c.WebSocketController(wss, config);
  20. //access
  21. const [aAll, aNormal, aSite, aReader, aOmnireader] = // eslint-disable-line no-unused-vars
  22. [config.mode, 'normal', 'site', 'reader', 'omnireader'];
  23. //multer
  24. const storage = multer.diskStorage({
  25. destination: (req, file, cb) => {
  26. cb(null, config.uploadDir);
  27. },
  28. filename: (req, file, cb) => {
  29. cb(null, utils.randomHexString(30));
  30. }
  31. });
  32. const upload = multer({ storage, limits: {fileSize: config.maxUploadFileSize} });
  33. //routes
  34. const routes = [
  35. ['POST', '/api/config', misc.getConfig.bind(misc), [aAll], {}],
  36. ['POST', '/api/reader/load-book', reader.loadBook.bind(reader), [aAll], {}],
  37. ['POST', '/api/reader/storage', reader.storage.bind(reader), [aAll], {}],
  38. ['POST', '/api/reader/upload-file', [upload.single('file'), reader.uploadFile.bind(reader)], [aAll], {}],
  39. ['POST', '/api/worker/get-state', worker.getState.bind(worker), [aAll], {}],
  40. ];
  41. //to app
  42. for (let route of routes) {
  43. let callbacks = [];
  44. let [httpMethod, path, controllers, access, options] = route;
  45. let controller = controllers;
  46. if (Array.isArray(controllers)) {
  47. controller = controllers[controllers.length - 1];
  48. callbacks = controllers.slice(0, -1);
  49. }
  50. access = new Set(access);
  51. let callback = () => {};
  52. if (access.has(config.mode)) {//allowed
  53. callback = async function(req, res) {
  54. try {
  55. const result = await controller(req, res, options);
  56. if (result !== false)
  57. res.send(result);
  58. } catch (e) {
  59. res.status(500).send({error: e.message});
  60. }
  61. };
  62. } else {//forbidden
  63. callback = async function(req, res) {
  64. res.status(403);
  65. };
  66. }
  67. callbacks.push(callback);
  68. switch (httpMethod) {
  69. case 'GET' :
  70. app.get(path, ...callbacks);
  71. break;
  72. case 'POST':
  73. app.post(path, ...callbacks);
  74. break;
  75. default:
  76. throw new Error(`initRoutes error: unknown httpMethod: ${httpMethod}`);
  77. }
  78. }
  79. }
  80. function initStatic(app, config) {
  81. const readerWorker = new ReaderWorker(config);
  82. //восстановление файлов в /tmp и /upload из webdav-storage, при необходимости
  83. app.use(async(req, res, next) => {
  84. if ((req.method !== 'GET' && req.method !== 'HEAD') ||
  85. !(req.path.indexOf('/tmp/') === 0 || req.path.indexOf('/upload/') === 0)
  86. ) {
  87. return next();
  88. }
  89. const filePath = `${config.publicDir}${req.path}`;
  90. //восстановим
  91. try {
  92. if (!await fs.pathExists(filePath)) {
  93. if (req.path.indexOf('/tmp/') === 0) {
  94. await readerWorker.restoreRemoteFile(req.path, '/tmp');
  95. } else if (req.path.indexOf('/upload/') === 0) {
  96. await readerWorker.restoreRemoteFile(req.path, '/upload');
  97. }
  98. }
  99. } catch(e) {
  100. log(LM_ERR, `static::restoreRemoteFile ${req.path} > ${e.message}`);
  101. }
  102. return next();
  103. });
  104. const tmpDir = `${config.publicDir}/tmp`;
  105. app.use(express.static(config.publicDir, {
  106. maxAge: '30d',
  107. setHeaders: (res, filePath) => {
  108. if (path.dirname(filePath) == tmpDir) {
  109. res.set('Content-Type', 'application/xml');
  110. res.set('Content-Encoding', 'gzip');
  111. }
  112. },
  113. }));
  114. }
  115. module.exports = {
  116. initRoutes
  117. }