mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 02:11:44 +03:00
faea2da596
- we're slowly trying to draw the lines between the backend and the frontend correctly - these files deal only with serving the frontend so they should live there - there are lots of mixed requires in these files, so having them in the right place makes that clear
87 lines
3.0 KiB
JavaScript
87 lines
3.0 KiB
JavaScript
const crypto = require('crypto');
|
|
const fs = require('fs-extra');
|
|
const path = require('path');
|
|
const errors = require('@tryghost/errors');
|
|
const config = require('../../../shared/config');
|
|
const urlUtils = require('../../../shared/url-utils');
|
|
const tpl = require('@tryghost/tpl');
|
|
|
|
const messages = {
|
|
imageNotFound: 'Image not found'
|
|
};
|
|
|
|
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;
|
|
|
|
return function servePublicFileMiddleware(req, res, next) {
|
|
if (content) {
|
|
res.writeHead(200, content.headers);
|
|
return res.end(content.body);
|
|
}
|
|
|
|
// send image files directly and let express handle content-length, etag, etc
|
|
if (type.match(/^image/)) {
|
|
return res.sendFile(filePath, (err) => {
|
|
if (err && err.status === 404) {
|
|
// ensure we're triggering basic asset 404 and not a templated 404
|
|
return next(new errors.NotFoundError({
|
|
message: tpl(messages.imageNotFound),
|
|
code: 'STATIC_FILE_NOT_FOUND',
|
|
property: err.path
|
|
}));
|
|
}
|
|
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
});
|
|
}
|
|
|
|
// modify text files before caching+serving to ensure URL placeholders are transformed
|
|
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, urlUtils.urlFor('home', true).replace(/\/$/, ''));
|
|
}
|
|
|
|
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 servePublicFileMiddleware(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;
|