Просмотр исходного кода

Merge pull request #2489 from Daiki51/feat/internal-redirect

Supports nginx internal redirect and Apache SendFile.
Yuki Takei 5 лет назад
Родитель
Сommit
9a95ac93f0

+ 4 - 0
src/server/routes/attachment.js

@@ -193,6 +193,10 @@ module.exports = function(crowi, app) {
       return res.sendStatus(304);
     }
 
+    if (fileUploader.canRespond()) {
+      return fileUploader.respond(res, attachment);
+    }
+
     let fileStream;
     try {
       fileStream = await fileUploader.findDeliveryFile(attachment);

+ 12 - 0
src/server/service/config-loader.js

@@ -137,6 +137,18 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type:    TYPES.BOOLEAN,
     default: false,
   },
+  USE_INTERNAL_REDIRECT: {
+    ns:      'crowi',
+    key:     'app:useInternalRedirect',
+    type:    TYPES.BOOLEAN,
+    default: false,
+  },
+  INTERNAL_REDIRECT_PATH: {
+    ns:      'crowi',
+    key:     'app:internalRedirectPath',
+    type:    TYPES.STRING,
+    default: "/growi-internal/",
+  },
   ELASTICSEARCH_URI: {
     ns:      'crowi',
     key:     'app:elasticsearchUri',

+ 25 - 0
src/server/service/file-uploader/local.js

@@ -4,6 +4,7 @@ const fs = require('fs');
 const path = require('path');
 const mkdir = require('mkdirp');
 const streamToPromise = require('stream-to-promise');
+const urljoin = require('url-join');
 
 module.exports = function(crowi) {
   const Uploader = require('./uploader');
@@ -92,5 +93,29 @@ module.exports = function(crowi) {
     return lib.doCheckLimit(uploadFileSize, maxFileSize, totalLimit);
   };
 
+  /**
+   * Checks if Uploader can respond to the HTTP request.
+   */
+  lib.canRespond = () => {
+    // Check whether to use internal redirect of nginx or Apache.
+    return process.env.FILE_UPLOAD == "local" && lib.configManager.getConfig('crowi', 'app:useInternalRedirect');
+  };
+
+  /**
+   * Respond to the HTTP request.
+   * @param {Response} res 
+   * @param {Response} attachment 
+   */
+  lib.respond = (res, attachment) => {
+    // Responce using internal redirect of nginx or Apache.
+    const storagePath = getFilePathOnStorage(attachment);
+    const relativePath = path.relative(crowi.publicDir, storagePath);
+    const internalPathRoot = lib.configManager.getConfig('crowi', 'app:internalRedirectPath');
+    const internalPath = urljoin(internalPathRoot, relativePath)
+    res.set('X-Accel-Redirect', internalPath);
+    res.set('X-Sendfile', storagePath);
+    return res.end();
+  };
+
   return lib;
 };

+ 15 - 0
src/server/service/file-uploader/uploader.js

@@ -54,6 +54,21 @@ class Uploader {
 
   }
 
+  /**
+   * Checks if Uploader can respond to the HTTP request.
+   */
+  canRespond() {
+    return false;
+  }
+
+  /**
+   * Respond to the HTTP request.
+   * @param {Response} res
+   * @param {Response} attachment
+   */
+  respond(res, attachment) {
+    throw new Error('Implement this');
+  }
 }
 
 module.exports = Uploader;