96 lines
1.9 KiB
JavaScript
96 lines
1.9 KiB
JavaScript
|
|
||
|
/*!
|
||
|
* Connect - favicon
|
||
|
* Copyright(c) 2010 Sencha Inc.
|
||
|
* Copyright(c) 2011 TJ Holowaychuk
|
||
|
* MIT Licensed
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Module dependencies.
|
||
|
*/
|
||
|
|
||
|
var crypto = require('crypto')
|
||
|
, fs = require('fs');
|
||
|
|
||
|
/**
|
||
|
* Favicon cache.
|
||
|
*/
|
||
|
|
||
|
var icon;
|
||
|
|
||
|
/**
|
||
|
* Return md5 hash of the given string and optional encoding,
|
||
|
* defaulting to hex.
|
||
|
*
|
||
|
* utils.md5('wahoo');
|
||
|
* // => "e493298061761236c96b02ea6aa8a2ad"
|
||
|
*
|
||
|
* @param {String} str
|
||
|
* @param {String} encoding
|
||
|
* @return {String}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
exports.md5 = function (str, encoding) {
|
||
|
return crypto
|
||
|
.createHash('md5')
|
||
|
.update(str)
|
||
|
.digest(encoding || 'hex');
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* By default serves the connect favicon, or the favicon
|
||
|
* located by the given `path`.
|
||
|
*
|
||
|
* Options:
|
||
|
*
|
||
|
* - `maxAge` cache-control max-age directive, defaulting to 1 day
|
||
|
*
|
||
|
* Examples:
|
||
|
*
|
||
|
* connect.createServer(
|
||
|
* connect.favicon()
|
||
|
* );
|
||
|
*
|
||
|
* connect.createServer(
|
||
|
* connect.favicon(__dirname + '/public/favicon.ico')
|
||
|
* );
|
||
|
*
|
||
|
* @param {String} path
|
||
|
* @param {Object} options
|
||
|
* @return {Function}
|
||
|
* @api public
|
||
|
*/
|
||
|
|
||
|
module.exports = function favicon(path, options) {
|
||
|
var options = options || {}
|
||
|
, path = path || __dirname + '/../public/favicon.ico'
|
||
|
, maxAge = options.maxAge || 86400000;
|
||
|
|
||
|
return function favicon(req, res, next) {
|
||
|
if ('/favicon.ico' == req.url) {
|
||
|
if (icon) {
|
||
|
res.writeHead(200, icon.headers);
|
||
|
res.end(icon.body);
|
||
|
} else {
|
||
|
fs.readFile(path, function (err, buf) {
|
||
|
if (err) return next(err);
|
||
|
icon = {
|
||
|
headers: {
|
||
|
'Content-Type': 'image/x-icon'
|
||
|
, 'Content-Length': buf.length
|
||
|
, 'ETag': '"' + exports.md5(buf) + '"'
|
||
|
, 'Cache-Control': 'public, max-age=' + (maxAge / 1000)
|
||
|
},
|
||
|
body: buf
|
||
|
};
|
||
|
res.writeHead(200, icon.headers);
|
||
|
res.end(icon.body);
|
||
|
});
|
||
|
}
|
||
|
} else {
|
||
|
next();
|
||
|
}
|
||
|
};
|
||
|
};
|