From 8971e3c02b19d98c5e3eba67bb4524a5f50d02f6 Mon Sep 17 00:00:00 2001 From: jomo Date: Tue, 21 Apr 2015 00:57:14 +0200 Subject: [PATCH] use new response module for renders + bug fixes --- lib/helpers.js | 39 +++++++------ lib/response.js | 14 ++--- lib/routes/avatars.js | 1 + lib/routes/renders.js | 133 +++++++++++++++--------------------------- lib/routes/skins.js | 5 +- lib/server.js | 4 +- test/test.js | 2 +- 7 files changed, 85 insertions(+), 113 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index de65da9..e55a872 100644 --- a/lib/helpers.js +++ b/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); }); } }); diff --git a/lib/response.js b/lib/response.js index 08c156c..7172c46 100644 --- a/lib/response.js +++ b/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; diff --git a/lib/routes/avatars.js b/lib/routes/avatars.js index 7b4f23d..259542d 100644 --- a/lib/routes/avatars.js +++ b/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 }); }); diff --git a/lib/routes/renders.js b/lib/routes/renders.js index 2b7ab26..3e9fcc2 100644 --- a/lib/routes/renders.js +++ b/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 +// 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 + }); + }); + }); + } +} + // GET render request -module.exports = function(req, res) { - var start = new Date(); +module.exports = function(req, callback) { 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 - }); - res.end("Invalid Render Type"); - return; - } - 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); } }; \ No newline at end of file diff --git a/lib/routes/skins.js b/lib/routes/skins.js index cd1ac9d..6666ecd 100644 --- a/lib/routes/skins.js +++ b/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 { diff --git a/lib/server.js b/lib/server.js index 9ac0097..aa70842 100644 --- a/lib/server.js +++ b/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); diff --git a/test/test.js b/test/test.js index 34f7afc..c287619 100644 --- a/test/test.js +++ b/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(); });