0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-27 22:49:56 -05:00
ghost/core/server/middleware/serve-favicon.js
Aileen Nowak d2f2888da0 Favicon URI (#7700)
closes #7688

- Use `/favicon.ico` and `/favicon.png` in blog app. Depending on type of storage (custom upload = local file storage), serves either from storage adapter with `read()` method or reads the bytes via `fs`.
- Redirects requests for `favicon.ico` to `favicon.png` if custom `png` icon is uploaded and vice versa.
- Redirect requests for `favicon.png` to `favicon.ico` if default icon is used (in `core/shared`).
- Changes the `{{asset}}` helper for favicon to not serve from theme assets anymore. It will either be served the custom blog-icon or the default one.
- The `{{@blog.icon}}` helper renders the url of the **uploaded** blog icon. It won't render the default icon.
2017-01-26 18:01:19 +00:00

88 lines
3.2 KiB
JavaScript

var fs = require('fs'),
path = require('path'),
storage = require('../storage'),
config = require('../config'),
utils = require('../utils'),
crypto = require('crypto'),
buildContentResponse,
content;
buildContentResponse = function buildContentResponse(ext, buf) {
content = {
headers: {
'Content-Type': 'image/' + ext,
'Content-Length': buf.length,
ETag: '"' + crypto.createHash('md5').update(buf, 'utf8').digest('hex') + '"',
'Cache-Control': 'public, max-age=' + utils.ONE_DAY_S
},
body: buf
};
return content;
};
// ### serveFavicon Middleware
// Handles requests to favicon.png and favicon.ico
function serveFavicon() {
var iconType,
filePath;
return function serveFavicon(req, res, next) {
if (req.path.match(/^\/favicon\.(ico|png)/i)) {
// CASE: favicon is default
// confusing: if you upload an icon, it's same logic as storing images
// we store as /content/images, because this is the url path images get requested via the browser
// we are using an express route to skip /content/images and the result is a image path
// based on config.getContentPath('images') + req.path
// in this case we don't use path rewrite, that's why we have to make it manually
filePath = config.get('theme:icon').replace(/\/content\/images\//, '');
var originalExtension = path.extname(filePath).toLowerCase(),
requestedExtension = path.extname(req.path).toLowerCase();
// CASE: custom favicon exists, load it from local file storage
if (config.get('theme:icon')) {
// depends on the uploaded icon extension
if (originalExtension !== requestedExtension) {
return res.redirect(302, '/favicon' + originalExtension);
}
storage.getStorage().read({path: filePath}).then(function readFile(buf, err) {
if (err) {
return next(err);
}
iconType = config.get('theme:icon').match(/\/favicon\.ico$/i) ? 'x-icon' : 'png';
content = buildContentResponse(iconType, buf);
res.writeHead(200, content.headers);
res.end(content.body);
});
} else {
filePath = 'core/shared/favicon.ico';
originalExtension = path.extname(filePath).toLowerCase();
// CASE: always redirect to .ico for default icon
if (originalExtension !== requestedExtension) {
return res.redirect(302, '/favicon.ico');
}
fs.readFile(filePath, function readFile(err, buf) {
if (err) {
return next(err);
}
content = buildContentResponse('x-icon', buf);
res.writeHead(200, content.headers);
res.end(content.body);
});
}
} else {
next();
}
};
}
module.exports = serveFavicon;