avatars.js 3.1 KB

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