Selaa lähdekoodia

use new response module for renders + bug fixes

jomo 10 vuotta sitten
vanhempi
sitoutus
8971e3c02b
7 muutettua tiedostoa jossa 85 lisäystä ja 113 poistoa
  1. 21 18
      lib/helpers.js
  2. 7 7
      lib/response.js
  3. 1 0
      lib/routes/avatars.js
  4. 48 85
      lib/routes/renders.js
  5. 4 1
      lib/routes/skins.js
  6. 3 1
      lib/server.js
  7. 1 1
      test/test.js

+ 21 - 18
lib/helpers.js

@@ -286,23 +286,26 @@ exp.get_avatar = function(rid, userId, helm, size, callback) {
 };
 
 // handles requests for +userId+ skins
-// callback: error, skin hash, image buffer
+// callback: error, skin hash, status, image buffer
 exp.get_skin = function(rid, userId, callback) {
   exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) {
-    // FIXME: err is not used / handled
-    var skinpath = path.join(__dirname, "..", config.skins_dir, skin_hash + ".png");
-    fs.exists(skinpath, function(exists) {
-      if (exists) {
-        logging.log(rid, "skin already exists, not downloading");
-        skins.open_skin(rid, skinpath, function(skin_err, img) {
-          callback(skin_err, skin_hash, img);
-        });
-      } else {
-        networking.save_texture(rid, skin_hash, skinpath, function(net_err, response, img) {
-          callback(net_err, skin_hash, img);
-        });
-      }
-    });
+    if (skin_hash) {
+      var skinpath = path.join(__dirname, "..", config.skins_dir, skin_hash + ".png");
+      fs.exists(skinpath, function(exists) {
+        if (exists) {
+          logging.log(rid, "skin already exists, not downloading");
+          skins.open_skin(rid, skinpath, function(skin_err, img) {
+            callback(skin_err || err, skin_hash, status, img);
+          });
+        } else {
+          networking.save_texture(rid, skin_hash, skinpath, function(net_err, response, img) {
+            callback(net_err || err, skin_hash, status, img);
+          });
+        }
+      });
+    } else {
+      callback(err, null, status, null);
+    }
   });
 };
 
@@ -317,9 +320,9 @@ function get_type(helm, body) {
 // handles creations of 3D renders
 // callback: error, skin hash, image buffer
 exp.get_render = function(rid, userId, scale, helm, body, callback) {
-  exp.get_skin(rid, userId, function(err, skin_hash, img) {
+  exp.get_skin(rid, userId, function(err, skin_hash, status, img) {
     if (!skin_hash) {
-      callback(err, -1, skin_hash, null);
+      callback(err, status, skin_hash, null);
       return;
     }
     var renderpath = path.join(__dirname, "..", config.renders_dir, [skin_hash, scale, get_type(helm, body)].join("-") + ".png");
@@ -344,7 +347,7 @@ exp.get_render = function(rid, userId, scale, helm, body, callback) {
               if (fs_err) {
                 logging.error(rid, fs_err.stack);
               }
-              callback(null, 2, skin_hash, img);
+              callback(null, 2, skin_hash, drawn_img);
             });
           }
         });

+ 7 - 7
lib/response.js

@@ -3,12 +3,12 @@ var config = require("./config");
 var crc = require("crc").crc32;
 
 var human_status = {
-  "-2": "user error",
-  "-1": "server error",
-  0: "none",
-  1: "cached",
-  2: "downloaded",
-  3: "checked",
+  "-2": "user error",   // e.g. invalid size
+  "-1": "server error", // e.g. network issues
+  0: "none",            // cached as null (user has no skin)
+  1: "cached",          // found on disk
+  2: "downloaded",      // profile downloaded, skin downloaded from mojang servers
+  3: "checked",         // profile re-downloaded (was too old), has no skin or skin cached
 };
 
 
@@ -64,7 +64,7 @@ module.exports = function(request, response, result) {
     // handle etag caching
     var incoming_etag = request.headers["if-none-match"];
     if (incoming_etag && incoming_etag === headers.Etag) {
-      logging.debug("Etag matches");
+      logging.debug(request.id, "Etag matches");
       response.writeHead(304, headers);
       response.end();
       return;

+ 1 - 0
lib/routes/avatars.js

@@ -19,6 +19,7 @@ function handle_default(img_status, userId, size, def, err, callback) {
         status: img_status,
         body: image,
         type: "image/png",
+        hash: def,
         err: resize_err || err
       });
     });

+ 48 - 85
lib/routes/renders.js

@@ -7,100 +7,66 @@ var skins = require("../skins");
 var path = require("path");
 var fs = require("fs");
 
-var human_status = {
-  0: "none",
-  1: "cached",
-  2: "downloaded",
-  3: "checked",
-  "-1": "error"
-};
-
 // valid types: head, body
 // helmet is query param
 // TODO: The Type logic should be two separate GET functions once response methods are extracted
 
-// GET render request
-module.exports = function(req, res) {
-  var start = new Date();
-  var raw_type = (req.url.path_list[1] || "");
-  var rid = req.id;
-
-  // validate type
-  if (raw_type !== "body" && raw_type !== "head") {
-    res.writeHead(422, {
-      "Content-Type": "text/plain",
-      "Response-Time": new Date() - start
+// default alex/steve images can be rendered, but
+// custom images will not be
+function handle_default(rid, scale, helm, body, img_status, userId, size, def, err, callback) {
+  if (def && def !== "steve" && def !== "alex") {
+    callback({
+      status: img_status,
+      redirect: def,
+      err: err
+    });
+  } else {
+    def = def || skins.default_skin(userId);
+    fs.readFile(path.join(__dirname, "..", "public", "images", def + "_skin.png"), function (fs_err, buf) {
+      // we render the default skins, but not custom images
+      renders.draw_model(rid, buf, scale, helm, body, function(render_err, def_img) {
+        callback({
+          status: img_status,
+          body: def_img,
+          type: "image/png",
+          hash: def,
+          err: render_err || fs_err || err
+        });
+      });
     });
-    res.end("Invalid Render Type");
-    return;
   }
+}
 
+// GET render request
+module.exports = function(req, callback) {
+  var raw_type = (req.url.path_list[1] || "");
+  var rid = req.id;
   var body = raw_type === "body";
   var userId = (req.url.path_list[2] || "").split(".")[0];
   var def = req.url.query.default;
   var scale = parseInt(req.url.query.scale) || config.default_scale;
   var helm = req.url.query.hasOwnProperty("helm");
-  var etag = null;
 
-  function sendimage(rid, http_status, img_status, image) {
-    logging.log(rid, "status:", http_status);
-    res.writeHead(http_status, {
-      "Content-Type": "image/png",
-      "Cache-Control": "max-age=" + config.browser_cache_time + ", public",
-      "Response-Time": new Date() - start,
-      "X-Storage-Type": human_status[img_status],
-      "X-Request-ID": rid,
-      "Access-Control-Allow-Origin": "*",
-      "Etag": '"' + etag + '"'
+  // validate type
+  if (raw_type !== "body" && raw_type !== "head") {
+    callback({
+      status: -2,
+      body: "Invalid Render Type"
     });
-    res.end(http_status === 304 ? null : image);
-  }
-
-  // default alex/steve images can be rendered, but
-  // custom images will not be
-  function handle_default(rid, http_status, img_status, userId) {
-    if (def && def !== "steve" && def !== "alex") {
-      logging.log(rid, "status: 301");
-      res.writeHead(301, {
-        "Cache-Control": "max-age=" + config.browser_cache_time + ", public",
-        "Response-Time": new Date() - start,
-        "X-Storage-Type": human_status[img_status],
-        "X-Request-ID": rid,
-        "Access-Control-Allow-Origin": "*",
-        "Location": def
-      });
-      res.end();
-    } else {
-      def = def || skins.default_skin(userId);
-      fs.readFile(path.join(__dirname, "..", "public", "images", def + "_skin.png"), function (err, buf) {
-        if (err) {
-          // errored while loading the default image, continuing with null image
-          logging.error(rid, "error loading default render image:", err);
-        }
-        // we render the default skins, but not custom images
-        renders.draw_model(rid, buf, scale, helm, body, function(render_err, def_img) {
-          if (render_err) {
-            logging.error(rid, "error while rendering default image:", render_err);
-          }
-          sendimage(rid, http_status, img_status, def_img);
-        });
-      });
-    }
+    return;
   }
 
   if (scale < config.min_scale || scale > config.max_scale) {
-    res.writeHead(422, {
-      "Content-Type": "text/plain",
-      "Response-Time": new Date() - start
+    callback({
+      status: -2,
+      body: "422 Invalid Scale"
     });
-    res.end("422 Invalid Scale");
     return;
   } else if (!helpers.id_valid(userId)) {
-    res.writeHead(422, {
-      "Content-Type": "text/plain",
-      "Response-Time": new Date() - start
+    callback({
+      status: -2,
+      body: "422 Invalid ID"
     });
-    res.end("422 Invalid ID");
     return;
   }
 
@@ -110,7 +76,6 @@ module.exports = function(req, res) {
 
   try {
     helpers.get_render(rid, userId, scale, helm, body, function(err, status, hash, image) {
-      logging.log(rid, "storage type:", human_status[status]);
       if (err) {
         logging.error(rid, err);
         if (err.code === "ENOENT") {
@@ -118,23 +83,21 @@ module.exports = function(req, res) {
           cache.remove_hash(rid, userId);
         }
       }
-      etag = hash && hash.substr(0, 32) || "none";
-      var matches = req.headers["if-none-match"] === '"' + etag + '"';
       if (image) {
-        var http_status = 200;
-        if (err) {
-          http_status = 503;
-        }
-        logging.debug(rid, "etag:", req.headers["if-none-match"]);
-        logging.debug(rid, "matches:", matches);
-        sendimage(rid, matches ? 304 : http_status, status, image);
+        callback({
+          status: status,
+          body: image,
+          type: "image/png",
+          hash: hash,
+          err: err
+        });
       } else {
         logging.log(rid, "image not found, using default.");
-        handle_default(rid, matches ? 304 : 200, status, userId);
+        handle_default(rid, scale, helm, body, status, userId, scale, def, err, callback);
       }
     });
   } catch(e) {
     logging.error(rid, "error:", e.stack);
-    handle_default(rid, 500, -1, userId);
+    handle_default(rid, scale, helm, body, -1, userId, scale, def, e, callback);
   }
 };

+ 4 - 1
lib/routes/skins.js

@@ -20,6 +20,7 @@ function handle_default(img_status, userId, def, err, callback) {
             status: img_status,
             body: buffer,
             type: "image/png",
+            hash: def,
             err: buf_err || lwip_err || err
           });
         });
@@ -52,11 +53,13 @@ module.exports = function(req, callback) {
   logging.debug(rid, "userid:", userId);
 
   try {
-    helpers.get_skin(rid, userId, function(err, hash, image) {
+    helpers.get_skin(rid, userId, function(err, hash, status, image) {
       if (image) {
         callback({
+          status: status,
           body: image,
           type: "image/png",
+          hash: hash,
           err: err
         });
       } else {

+ 3 - 1
lib/server.js

@@ -85,7 +85,9 @@ function requestHandler(req, res) {
         });
         break;
         case "renders":
-        routes.renders(req, res);
+        routes.renders(req, function(result) {
+          response(req, res, result);
+        });
         break;
         case "capes":
         routes.capes(req, res);

+ 1 - 1
test/test.js

@@ -432,7 +432,7 @@ describe("Crafatar", function() {
 
       describe("Networking: Skin", function() {
         it("should not fail (uuid)", function(done) {
-          helpers.get_skin(rid, id, function(err, hash, img) {
+          helpers.get_skin(rid, id, function(err, hash, status, img) {
             assert.strictEqual(err, null);
             done();
           });