mirror of
https://github.com/codex-team/codex.docs.git
synced 2025-08-08 15:05:26 +02:00
Fix serving static files
This commit is contained in:
parent
d54a5b740a
commit
4801b038cc
11 changed files with 57 additions and 29 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -75,3 +75,4 @@ typings/
|
||||||
|
|
||||||
# Uploads
|
# Uploads
|
||||||
/public/uploads
|
/public/uploads
|
||||||
|
/public/uploads_test
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"port": 3000,
|
"port": 3000,
|
||||||
"database": ".db"
|
"database": ".db",
|
||||||
|
"uploads": "public/uploads"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ if (fs.existsSync(path.resolve(__dirname, configPath))) {
|
||||||
} else {
|
} else {
|
||||||
config = {
|
config = {
|
||||||
database: '.db',
|
database: '.db',
|
||||||
port: 3000
|
port: 3000,
|
||||||
|
uploads: 'public/uploads'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"port": 3000,
|
"port": 3000,
|
||||||
"database": ".db"
|
"database": ".db",
|
||||||
|
"uploads": "public/uploads"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"port": 3001,
|
"port": 3001,
|
||||||
"database": ".testdb",
|
"database": ".testdb",
|
||||||
"rcFile": "./test/.codexdocsrc"
|
"rcFile": "./test/.codexdocsrc",
|
||||||
|
"uploads": "public/uploads_test"
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
"express": "~4.16.0",
|
"express": "~4.16.0",
|
||||||
"file-type": "^10.7.1",
|
"file-type": "^10.7.1",
|
||||||
"http-errors": "~1.7.1",
|
"http-errors": "~1.7.1",
|
||||||
|
"mime": "^2.4.0",
|
||||||
"module-dispatcher": "^2.0.0",
|
"module-dispatcher": "^2.0.0",
|
||||||
"morgan": "~1.9.0",
|
"morgan": "~1.9.0",
|
||||||
"multer": "^1.3.1",
|
"multer": "^1.3.1",
|
||||||
|
@ -46,8 +47,8 @@
|
||||||
"babel-loader": "^8.0.2",
|
"babel-loader": "^8.0.2",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"chai-http": "^4.0.0",
|
"chai-http": "^4.0.0",
|
||||||
"codex.editor.image": "^2.0.3",
|
|
||||||
"codex.editor.code": "^2.3.1",
|
"codex.editor.code": "^2.3.1",
|
||||||
|
"codex.editor.image": "^2.0.3",
|
||||||
"codex.editor.inline-code": "^1.2.0",
|
"codex.editor.inline-code": "^1.2.0",
|
||||||
"codex.editor.list": "^1.2.3",
|
"codex.editor.list": "^1.2.3",
|
||||||
"codex.editor.marker": "^1.0.1",
|
"codex.editor.marker": "^1.0.1",
|
||||||
|
@ -79,6 +80,7 @@
|
||||||
"postcss-nested-ancestors": "^2.0.0",
|
"postcss-nested-ancestors": "^2.0.0",
|
||||||
"postcss-nesting": "^7.0.0",
|
"postcss-nesting": "^7.0.0",
|
||||||
"postcss-smart-import": "^0.7.6",
|
"postcss-smart-import": "^0.7.6",
|
||||||
|
"rimraf": "^2.6.3",
|
||||||
"sinon": "^7.0.0",
|
"sinon": "^7.0.0",
|
||||||
"webpack": "^4.17.1",
|
"webpack": "^4.17.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
|
|
16
src/app.js
16
src/app.js
|
@ -4,8 +4,6 @@ const path = require('path');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const logger = require('morgan');
|
const logger = require('morgan');
|
||||||
const rcParser = require('./utils/rcparser');
|
const rcParser = require('./utils/rcparser');
|
||||||
const FileModel = require('./models/file');
|
|
||||||
|
|
||||||
const routes = require('./routes');
|
const routes = require('./routes');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
@ -22,19 +20,7 @@ app.use(logger('dev'));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.static(
|
app.use(express.static(path.join(__dirname, '../public')));
|
||||||
path.join(__dirname, '../public'),
|
|
||||||
{
|
|
||||||
setHeaders: async (res, pathToFile) => {
|
|
||||||
const filename = path.basename(pathToFile);
|
|
||||||
const file = await FileModel.getByFilename(filename);
|
|
||||||
|
|
||||||
if (file._id && file.mimetype) {
|
|
||||||
res.setHeader('content-type', file.mimetype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
));
|
|
||||||
|
|
||||||
app.use('/', routes);
|
app.use('/', routes);
|
||||||
// catch 404 and forward to error handler
|
// catch 404 and forward to error handler
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
const fileType = require('file-type');
|
const fileType = require('file-type');
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const nodePath = require('path');
|
||||||
|
|
||||||
const Model = require('../models/file');
|
const Model = require('../models/file');
|
||||||
const { random16 } = require('../utils/crypto');
|
const { random16 } = require('../utils/crypto');
|
||||||
const { deepMerge } = require('../utils/objects');
|
const { deepMerge } = require('../utils/objects');
|
||||||
|
const config = require('../../config');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Transport
|
* @class Transport
|
||||||
|
@ -26,7 +28,7 @@ class Transport {
|
||||||
* @return {Promise<FileData>}
|
* @return {Promise<FileData>}
|
||||||
*/
|
*/
|
||||||
static async save(multerData, map) {
|
static async save(multerData, map) {
|
||||||
const { originalname: name, filename, path, size, mimetype } = multerData;
|
const { originalname: name, path, filename, size, mimetype } = multerData;
|
||||||
|
|
||||||
const file = new Model({ name, filename, path, size, mimetype });
|
const file = new Model({ name, filename, path, size, mimetype });
|
||||||
|
|
||||||
|
@ -52,14 +54,15 @@ class Transport {
|
||||||
const buffer = await fetchedFile.buffer();
|
const buffer = await fetchedFile.buffer();
|
||||||
const filename = await random16();
|
const filename = await random16();
|
||||||
|
|
||||||
fs.writeFileSync(`public/uploads/${filename}`, buffer);
|
|
||||||
|
|
||||||
const type = fileType(buffer);
|
const type = fileType(buffer);
|
||||||
|
const ext = type ? type.ext : nodePath.extname(url).slice(1);
|
||||||
|
|
||||||
|
fs.writeFileSync(`${config.uploads}/${filename}.${ext}`, buffer);
|
||||||
|
|
||||||
const file = new Model({
|
const file = new Model({
|
||||||
name: url,
|
name: url,
|
||||||
filename,
|
filename: `${filename}.${ext}`,
|
||||||
path: `/uploads/${filename}`,
|
path: `${config.uploads}/${filename}.${ext}`,
|
||||||
size: buffer.length,
|
size: buffer.length,
|
||||||
mimetype: type ? type.mime : fetchedFile.headers.get('content-type')
|
mimetype: type ? type.mime : fetchedFile.headers.get('content-type')
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,31 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const multer = require('multer');
|
const multer = require('multer');
|
||||||
|
const mime = require('mime')
|
||||||
const Transport = require('../../controllers/transport');
|
const Transport = require('../../controllers/transport');
|
||||||
|
const { random16 } = require('../../utils/crypto');
|
||||||
|
const config = require('../../../config');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multer storage for uploaded files and images
|
||||||
|
* @type {DiskStorage|DiskStorage}
|
||||||
|
*/
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: (req, file, cb) => {
|
||||||
|
cb(null, config.uploads || 'public/uploads');
|
||||||
|
},
|
||||||
|
filename: async (req, file, cb) => {
|
||||||
|
const filename = await random16();
|
||||||
|
|
||||||
|
cb(null, `${filename}.${mime.getExtension(file.mimetype)}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multer middleware for image uploading
|
* Multer middleware for image uploading
|
||||||
*/
|
*/
|
||||||
const imageUploader = multer({
|
const imageUploader = multer({
|
||||||
dest: 'public/uploads/',
|
storage,
|
||||||
fileFilter: (req, file, cb) => {
|
fileFilter: (req, file, cb) => {
|
||||||
if (!/image/.test(file.mimetype)) {
|
if (!/image/.test(file.mimetype)) {
|
||||||
cb(null, false);
|
cb(null, false);
|
||||||
|
@ -22,7 +40,7 @@ const imageUploader = multer({
|
||||||
* Multer middleware for file uploading
|
* Multer middleware for file uploading
|
||||||
*/
|
*/
|
||||||
const fileUploader = multer({
|
const fileUploader = multer({
|
||||||
dest: 'public/uploads/'
|
storage
|
||||||
}).fields([ { name: 'file', maxCount: 1 } ]);
|
}).fields([ { name: 'file', maxCount: 1 } ]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,6 +3,7 @@ const path = require('path');
|
||||||
const fileType = require('file-type');
|
const fileType = require('file-type');
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
const chaiHTTP = require('chai-http');
|
const chaiHTTP = require('chai-http');
|
||||||
|
const rimraf = require('rimraf');
|
||||||
const {expect} = chai;
|
const {expect} = chai;
|
||||||
|
|
||||||
const {app} = require('../../bin/www');
|
const {app} = require('../../bin/www');
|
||||||
|
@ -17,6 +18,10 @@ describe('Transport routes: ', () => {
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
agent = chai.request.agent(app);
|
agent = chai.request.agent(app);
|
||||||
|
|
||||||
|
if (!fs.existsSync('./' + config.uploads)) {
|
||||||
|
fs.mkdirSync('./' + config.uploads);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
|
@ -25,6 +30,10 @@ describe('Transport routes: ', () => {
|
||||||
if (fs.existsSync(pathToDB)) {
|
if (fs.existsSync(pathToDB)) {
|
||||||
fs.unlinkSync(pathToDB);
|
fs.unlinkSync(pathToDB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fs.existsSync('./' + config.uploads)) {
|
||||||
|
rimraf.sync('./' + config.uploads);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Uploading an image', async () => {
|
it('Uploading an image', async () => {
|
||||||
|
@ -102,7 +111,7 @@ describe('Transport routes: ', () => {
|
||||||
.get(file.path);
|
.get(file.path);
|
||||||
|
|
||||||
expect(getRes).to.have.status(200);
|
expect(getRes).to.have.status(200);
|
||||||
expect(getRes).to.have.header('content-type', file.mimetype);
|
expect(getRes).to.have.header('content-type', new RegExp(`^${file.mimetype}`));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Uploading a file with map option', async () => {
|
it('Uploading a file with map option', async () => {
|
||||||
|
|
|
@ -3730,6 +3730,11 @@ mime@^1.4.1:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||||
|
|
||||||
|
mime@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6"
|
||||||
|
integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==
|
||||||
|
|
||||||
mimic-fn@^1.0.0:
|
mimic-fn@^1.0.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
|
||||||
|
@ -5293,7 +5298,7 @@ rgba-regex@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
|
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
|
||||||
|
|
||||||
rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2:
|
rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@~2.6.2:
|
||||||
version "2.6.3"
|
version "2.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue