0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-03 23:00:14 -05:00
ghost/core/server/web/shared/middlewares/serve-public-file.js
Fabien O'Carroll ed1a42f7f3 Exported raw middleware from serve-public-file
no-issue

The current public file middleware handles route matching itself, which
means it is applied to express via the use method. Due to use being a
"global" application of middleware, this means it is not possible to
apply a labs middleware before the public file serving middleware
without it affecting the entire route stack.

This commit exports a piece of raw middleware that can be used with the
get method of express, so that we can attach middleware beforehand.

This will be used to conditionally serve the members specific public
files, based on the labs flag for members.
2019-04-24 12:46:00 +02:00

62 lines
2.3 KiB
JavaScript

const crypto = require('crypto');
const fs = require('fs-extra');
const path = require('path');
const config = require('../../../config');
const urlService = require('../../../services/url');
function createPublicFileMiddleware(file, type, maxAge) {
let content;
const publicFilePath = config.get('paths').publicFilePath;
const filePath = file.match(/^public/) ? path.join(publicFilePath, file.replace(/^public/, '')) : path.join(publicFilePath, file);
const blogRegex = /(\{\{blog-url\}\})/g;
const apiRegex = /(\{\{api-url\}\})/g;
return function servePublicFile(req, res, next) {
if (content) {
res.writeHead(200, content.headers);
return res.end(content.body);
}
fs.readFile(filePath, (err, buf) => {
if (err) {
return next(err);
}
let str = buf.toString();
if (type === 'text/xsl' || type === 'text/plain' || type === 'application/javascript') {
str = str.replace(blogRegex, urlService.utils.urlFor('home', true).replace(/\/$/, ''));
str = str.replace(apiRegex, urlService.utils.urlFor('api', {cors: true, version: 'v0.1', versionType: 'content'}, true));
}
content = {
headers: {
'Content-Type': type,
'Content-Length': Buffer.from(str).length,
ETag: `"${crypto.createHash('md5').update(str, 'utf8').digest('hex')}"`,
'Cache-Control': `public, max-age=${maxAge}`
},
body: str
};
res.writeHead(200, content.headers);
res.end(content.body);
});
};
}
// ### servePublicFile Middleware
// Handles requests to robots.txt and favicon.ico (and caches them)
function servePublicFile(file, type, maxAge) {
const publicFileMiddleware = createPublicFileMiddleware(file, type, maxAge);
return function servePublicFile(req, res, next) {
if (req.path === '/' + file) {
return publicFileMiddleware(req, res, next);
} else {
return next();
}
};
}
module.exports = servePublicFile;
module.exports.servePublicFile = servePublicFile;
module.exports.createPublicFileMiddleware = createPublicFileMiddleware;