avatars.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. var networking = require('../modules/networking');
  2. var logging = require('../modules/logging');
  3. var helpers = require('../modules/helpers');
  4. var router = require('express').Router();
  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. router.get('/skins/:uuid.:ext?', function(req, res) {
  15. var uuid = req.params.uuid;
  16. var start = new Date();
  17. if (!helpers.uuid_valid(uuid)) {
  18. res.status(422).send("422 Invalid UUID");
  19. return;
  20. }
  21. // strip dashes
  22. uuid = uuid.replace(/-/g, "");
  23. try {
  24. helpers.get_image_hash(uuid, function(err, status, hash) {
  25. if (hash) {
  26. res.writeHead(301, {
  27. 'Location': "http://textures.minecraft.net/texture/" + hash,
  28. 'Cache-Control': 'max-age=' + config.browser_cache_time + ', public',
  29. 'Response-Time': new Date() - start,
  30. 'X-Storage-Type': human_status[status]
  31. });
  32. res.end();
  33. } else if (!err) {
  34. res.writeHead(404, {
  35. 'Cache-Control': 'max-age=' + config.browser_cache_time + ', public',
  36. 'Response-Time': new Date() - start,
  37. 'X-Storage-Type': human_status[status]
  38. });
  39. res.end("404 Not found");
  40. } else {
  41. res.status(500).send("500 Internal server error");
  42. }
  43. });
  44. } catch(e) {
  45. logging.error("Error!");
  46. logging.error(e);
  47. res.status(500).send("500 Internal server error");
  48. }
  49. });
  50. /* GET avatar request. */
  51. router.get('/avatars/:uuid.:ext?', function(req, res) {
  52. var uuid = req.params.uuid;
  53. var size = req.query.size || config.default_size;
  54. var def = req.query.default;
  55. var helm = req.query.hasOwnProperty('helm');
  56. var start = new Date();
  57. var etag = null;
  58. // Prevent app from crashing/freezing
  59. if (size < config.min_size || size > config.max_size) {
  60. // "Unprocessable Entity", valid request, but semantically erroneous:
  61. // https://tools.ietf.org/html/rfc4918#page-78
  62. res.status(422).send("422 Invalid size");
  63. return;
  64. } else if (!helpers.uuid_valid(uuid)) {
  65. res.status(422).send("422 Invalid UUID");
  66. return;
  67. }
  68. // strip dashes
  69. uuid = uuid.replace(/-/g, "");
  70. try {
  71. helpers.get_avatar(uuid, helm, size, function(err, status, image, hash) {
  72. logging.log(uuid + " - " + human_status[status]);
  73. if (err) {
  74. logging.error(err);
  75. }
  76. etag = hash && hash.substr(0, 32) + (helm ? "-helm-" : "-face-") + size || "none";
  77. var matches = req.get("If-None-Match") == '"' + etag + '"';
  78. if (image) {
  79. var http_status = 200;
  80. if (matches) {
  81. http_status = 304;
  82. } else if (err) {
  83. http_status = 503;
  84. }
  85. console.log("matches: " + matches);
  86. console.log("status: " + http_status);
  87. sendimage(http_status, status, image);
  88. } else {
  89. handle_default(404, status);
  90. }
  91. });
  92. } catch(e) {
  93. logging.error("Error!");
  94. logging.error(e);
  95. handle_default(500, status);
  96. }
  97. function handle_default(http_status, img_status) {
  98. if (def && def != "steve" && def != "alex") {
  99. res.writeHead(301, {
  100. 'Cache-Control': 'max-age=' + config.browser_cache_time + ', public',
  101. 'Response-Time': new Date() - start,
  102. 'X-Storage-Type': human_status[img_status],
  103. 'Location': def
  104. });
  105. res.end();
  106. } else {
  107. def = def || skins.default_skin(uuid);
  108. skins.resize_img("public/images/" + def + ".png", size, function(err, image) {
  109. sendimage(http_status, img_status, image);
  110. });
  111. }
  112. }
  113. function sendimage(http_status, img_status, image) {
  114. res.writeHead(http_status, {
  115. 'Content-Type': 'image/png',
  116. 'Cache-Control': 'max-age=' + config.browser_cache_time + ', public',
  117. 'Response-Time': new Date() - start,
  118. 'X-Storage-Type': human_status[img_status],
  119. 'Etag': '"' + etag + '"'
  120. });
  121. res.end(http_status == 304 ? null : image);
  122. }
  123. });
  124. module.exports = router;