You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
1.9 KiB

8 years ago
  1. /*!
  2. * Connect - favicon
  3. * Copyright(c) 2010 Sencha Inc.
  4. * Copyright(c) 2011 TJ Holowaychuk
  5. * MIT Licensed
  6. */
  7. /**
  8. * Module dependencies.
  9. */
  10. var crypto = require('crypto')
  11. , fs = require('fs');
  12. /**
  13. * Favicon cache.
  14. */
  15. var icon;
  16. /**
  17. * Return md5 hash of the given string and optional encoding,
  18. * defaulting to hex.
  19. *
  20. * utils.md5('wahoo');
  21. * // => "e493298061761236c96b02ea6aa8a2ad"
  22. *
  23. * @param {String} str
  24. * @param {String} encoding
  25. * @return {String}
  26. * @api public
  27. */
  28. exports.md5 = function (str, encoding) {
  29. return crypto
  30. .createHash('md5')
  31. .update(str)
  32. .digest(encoding || 'hex');
  33. };
  34. /**
  35. * By default serves the connect favicon, or the favicon
  36. * located by the given `path`.
  37. *
  38. * Options:
  39. *
  40. * - `maxAge` cache-control max-age directive, defaulting to 1 day
  41. *
  42. * Examples:
  43. *
  44. * connect.createServer(
  45. * connect.favicon()
  46. * );
  47. *
  48. * connect.createServer(
  49. * connect.favicon(__dirname + '/public/favicon.ico')
  50. * );
  51. *
  52. * @param {String} path
  53. * @param {Object} options
  54. * @return {Function}
  55. * @api public
  56. */
  57. module.exports = function favicon(path, options) {
  58. var options = options || {}
  59. , path = path || __dirname + '/../public/favicon.ico'
  60. , maxAge = options.maxAge || 86400000;
  61. return function favicon(req, res, next) {
  62. if ('/favicon.ico' == req.url) {
  63. if (icon) {
  64. res.writeHead(200, icon.headers);
  65. res.end(icon.body);
  66. } else {
  67. fs.readFile(path, function (err, buf) {
  68. if (err) return next(err);
  69. icon = {
  70. headers: {
  71. 'Content-Type': 'image/x-icon'
  72. , 'Content-Length': buf.length
  73. , 'ETag': '"' + exports.md5(buf) + '"'
  74. , 'Cache-Control': 'public, max-age=' + (maxAge / 1000)
  75. },
  76. body: buf
  77. };
  78. res.writeHead(200, icon.headers);
  79. res.end(icon.body);
  80. });
  81. }
  82. } else {
  83. next();
  84. }
  85. };
  86. };