avatars.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. var router = require("express").Router();
  2. var networking = require("../modules/networking");
  3. var logging = require("../modules/logging");
  4. var helpers = require("../modules/helpers");
  5. var config = require("../modules/config");
  6. var skins = require("../modules/skins");
  7. var human_status = {
  8. 0: "none",
  9. 1: "cached",
  10. 2: "downloaded",
  11. 3: "checked",
  12. "-1": "error"
  13. };
  14. /* GET avatar request. */
  15. router.get("/:uuid.:ext?", function(req, res) {
  16. var uuid = req.params.uuid;
  17. var size = parseInt(req.query.size) || config.default_size;
  18. var def = req.query.default;
  19. var helm = req.query.hasOwnProperty("helm");
  20. var start = new Date();
  21. var etag = null;
  22. // Prevent app from crashing/freezing
  23. if (size < config.min_size || size > config.max_size) {
  24. // "Unprocessable Entity", valid request, but semantically erroneous:
  25. // https://tools.ietf.org/html/rfc4918#page-78
  26. res.status(422).send("422 Invalid size");
  27. return;
  28. } else if (!helpers.uuid_valid(uuid)) {
  29. res.status(422).send("422 Invalid UUID");
  30. return;
  31. }
  32. // strip dashes, to lower case
  33. uuid = uuid.replace(/-/g, "").toLowerCase();
  34. try {
  35. helpers.get_avatar(uuid, helm, size, function(err, status, image, hash) {
  36. logging.log(uuid + " - " + human_status[status]);
  37. if (err) {
  38. logging.error(err);
  39. }
  40. etag = hash && hash.substr(0, 32) || "none";
  41. var matches = req.get("If-None-Match") == "'" + etag + "'";
  42. if (image) {
  43. var http_status = 200;
  44. if (matches) {
  45. http_status = 304;
  46. } else if (err) {
  47. http_status = 503;
  48. }
  49. logging.debug("Etag: " + req.get("If-None-Match"));
  50. logging.debug("matches: " + matches);
  51. logging.log("status: " + http_status);
  52. sendimage(http_status, status, image);
  53. } else {
  54. handle_default(404, status);
  55. }
  56. });
  57. } catch(e) {
  58. logging.error("Error!");
  59. logging.error(e);
  60. handle_default(500, status);
  61. }
  62. function handle_default(http_status, img_status) {
  63. if (def && def != "steve" && def != "alex") {
  64. res.writeHead(301, {
  65. "Cache-Control": "max-age=" + config.browser_cache_time + ", public",
  66. "Response-Time": new Date() - start,
  67. "X-Storage-Type": human_status[img_status],
  68. "Access-Control-Allow-Origin": "*",
  69. "Location": def
  70. });
  71. res.end();
  72. } else {
  73. def = def || skins.default_skin(uuid);
  74. skins.resize_img("public/images/" + def + ".png", size, function(err, image) {
  75. sendimage(http_status, img_status, image);
  76. });
  77. }
  78. }
  79. function sendimage(http_status, img_status, image) {
  80. res.writeHead(http_status, {
  81. "Content-Type": "image/png",
  82. "Cache-Control": "max-age=" + config.browser_cache_time + ", public",
  83. "Response-Time": new Date() - start,
  84. "X-Storage-Type": human_status[img_status],
  85. "Access-Control-Allow-Origin": "*",
  86. "Etag": '"' + etag + '"'
  87. });
  88. res.end(http_status == 304 ? null : image);
  89. }
  90. });
  91. module.exports = router;