avatars.js 4.2 KB

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