drop support for usernames

Mojang has disabled their legacy skins API:
https://twitter.com/MojangSupport/status/964511258601865216

With their API rate limits, it's now practially impossible
for us to support usernames.

Fixes #142. The default parameter allows using:

- UUID
- URL
- MHF_Alex
- MHF_Steve
- Alex
- Steve

Contrary to UUIDs, using alex/steve doesn't redirect
and instead provides the skin from a locally stored file.
This commit is contained in:
jomo 2018-02-16 18:01:41 +01:00
parent a187fb26d4
commit dff58c66e7
11 changed files with 176 additions and 582 deletions

View File

@ -8,7 +8,7 @@ var path = require("path");
var fs = require("fs"); var fs = require("fs");
// 0098cb60-fa8e-427c-b299-793cbd302c9a // 0098cb60-fa8e-427c-b299-793cbd302c9a
var valid_user_id = /^([0-9a-f-A-F-]{32,36}|[a-zA-Z0-9_]{1,16})$/; // uuid|username var valid_user_id = /^[0-9a-f-A-F-]{32,36}$/; // uuid
var hash_pattern = /[0-9a-f]+$/; var hash_pattern = /[0-9a-f]+$/;
// gets the hash from the textures.minecraft.net +url+ // gets the hash from the textures.minecraft.net +url+
@ -22,10 +22,7 @@ function get_hash(url) {
// callback: error, skin hash, slim // callback: error, skin hash, slim
function store_skin(rid, userId, profile, cache_details, callback) { function store_skin(rid, userId, profile, cache_details, callback) {
networking.get_skin_info(rid, userId, profile, function(err, url, slim) { networking.get_skin_info(rid, userId, profile, function(err, url, slim) {
if (!err && userId.length > 16) { if (err) {
// updating username with model info from uuid details
cache.set_slim(rid, profile.name, slim);
} else {
slim = cache_details ? cache_details.slim : undefined; slim = cache_details ? cache_details.slim : undefined;
} }
@ -161,7 +158,6 @@ function resume(userId, type, err, hash, slim) {
// image type should be called back on // image type should be called back on
// callback: error, image hash, slim // callback: error, image hash, slim
function store_images(rid, userId, cache_details, type, callback) { function store_images(rid, userId, cache_details, type, callback) {
var is_uuid = userId.length > 16;
if (requests[type]["!" + userId]) { if (requests[type]["!" + userId]) {
logging.debug(rid, "adding to request queue"); logging.debug(rid, "adding to request queue");
push_request(userId, type, callback); push_request(userId, type, callback);
@ -169,8 +165,8 @@ function store_images(rid, userId, cache_details, type, callback) {
// add request to the queue // add request to the queue
push_request(userId, type, callback); push_request(userId, type, callback);
networking.get_profile(rid, (is_uuid ? userId : null), function(err, profile) { networking.get_profile(rid, userId, function(err, profile) {
if (err || (is_uuid && !profile)) { if (err || !profile) {
// error or uuid without profile // error or uuid without profile
if (!err && !profile) { if (!err && !profile) {
// no error, but uuid without profile // no error, but uuid without profile
@ -212,8 +208,8 @@ function store_images(rid, userId, cache_details, type, callback) {
var exp = {}; var exp = {};
// returns true if the +userId+ is a valid userId or username // returns true if the +userId+ is a valid userId
// the userId may be not exist, however // the UUID might not exist, however
exp.id_valid = function(userId) { exp.id_valid = function(userId) {
return valid_user_id.test(userId); return valid_user_id.test(userId);
}; };

View File

@ -6,29 +6,10 @@ var skins = require("./skins");
require("./object-patch"); require("./object-patch");
var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/"; var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
var skins_url = "https://skins.minecraft.net/MinecraftSkins/";
var capes_url = "https://skins.minecraft.net/MinecraftCloaks/";
var textures_url = "http://textures.minecraft.net/texture/"; var textures_url = "http://textures.minecraft.net/texture/";
var mojang_urls = [skins_url, capes_url];
var exp = {}; var exp = {};
// helper method that calls `get_username_url` or `get_uuid_info` based on the +usedId+
// +userId+ is used for usernames, while +profile+ is used for UUIDs
// callback: error, url, slim
function get_info(rid, userId, profile, type, callback) {
if (userId.length <= 16) {
// username
exp.get_username_url(rid, userId, type, function(err, url) {
callback(err, url || null, undefined);
});
} else {
exp.get_uuid_info(profile, type, function(url, slim) {
callback(null, url || null, slim);
});
}
}
// performs a GET request to the +url+ // performs a GET request to the +url+
// +options+ object includes these options: // +options+ object includes these options:
// encoding (string), default is to return a buffer // encoding (string), default is to return a buffer
@ -103,24 +84,6 @@ exp.get_from = function(rid, url, callback) {
}); });
}; };
// make a request to skins.miencraft.net
// the skin url is taken from the HTTP redirect
// type reference is above
exp.get_username_url = function(rid, name, type, callback) {
type = Number(type === "CAPE");
exp.get_from(rid, mojang_urls[type] + name + ".png", function(body, response, err) {
if (!err) {
if (response) {
callback(err, response.statusCode === 404 ? null : response.headers.location);
} else {
callback(err, null);
}
} else {
callback(err, null);
}
});
};
// gets the URL for a skin/cape from the profile // gets the URL for a skin/cape from the profile
// +type+ "SKIN" or "CAPE", specifies which to retrieve // +type+ "SKIN" or "CAPE", specifies which to retrieve
// callback: url, slim // callback: url, slim
@ -139,15 +102,12 @@ exp.get_uuid_info = function(profile, type, callback) {
slim = Object.get(profile, "textures.SKIN.metadata.model") === "slim"; slim = Object.get(profile, "textures.SKIN.metadata.model") === "slim";
} }
callback(url || null, !!slim); callback(null, url || null, !!slim);
}; };
// make a request to sessionserver for +uuid+ // make a request to sessionserver for +uuid+
// callback: error, profile // callback: error, profile
exp.get_profile = function(rid, uuid, callback) { exp.get_profile = function(rid, uuid, callback) {
if (!uuid) {
callback(null, null);
} else {
exp.get_from_options(rid, session_url + uuid, { encoding: "utf8" }, function(body, response, err) { exp.get_from_options(rid, session_url + uuid, { encoding: "utf8" }, function(body, response, err) {
try { try {
body = body ? JSON.parse(body) : null; body = body ? JSON.parse(body) : null;
@ -162,20 +122,19 @@ exp.get_profile = function(rid, uuid, callback) {
} }
} }
}); });
}
}; };
// get the skin URL and type for +userId+ // get the skin URL and type for +userId+
// +profile+ is used if +userId+ is a uuid // +profile+ is used if +userId+ is a uuid
// callback: error, url, slim // callback: error, url, slim
exp.get_skin_info = function(rid, userId, profile, callback) { exp.get_skin_info = function(rid, userId, profile, callback) {
get_info(rid, userId, profile, "SKIN", callback); exp.get_uuid_info(profile, "SKIN", callback);
}; };
// get the cape URL for +userId+ // get the cape URL for +userId+
// +profile+ is used if +userId+ is a uuid // +profile+ is used if +userId+ is a uuid
exp.get_cape_url = function(rid, userId, profile, callback) { exp.get_cape_url = function(rid, userId, profile, callback) {
get_info(rid, userId, profile, "CAPE", callback); exp.get_uuid_info(profile, "CAPE", callback);
}; };
// download the +tex_hash+ image from the texture server // download the +tex_hash+ image from the texture server

View File

@ -1,4 +1,4 @@
var valid_user_id = /^([0-9a-f-A-F-]{32,36}|[a-zA-Z0-9_]{1,16})$/; // uuid|username var valid_user_id = /^[0-9a-f-A-F-]{32,36}$/; // uuid
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.onload = function() { xhr.onload = function() {
@ -9,24 +9,14 @@ xhr.onload = function() {
status[key] = elem[key]; status[key] = elem[key];
}); });
var textures = status["textures.minecraft.net"] !== "green"; var textures_err = status["textures.minecraft.net"] !== "green";
var session = status["sessionserver.mojang.com"] !== "green"; var session_err = status["sessionserver.mojang.com"] !== "green";
var skins = status["skins.minecraft.net"] !== "green";
var error = null;
if (textures || session && skins) { if (textures_err || session_err) {
error = "all";
} else if (skins) {
error = "username";
} else if (session) {
error = "UUID";
}
if (error) {
var warn = document.createElement("div"); var warn = document.createElement("div");
warn.setAttribute("class", "alert alert-warning"); warn.setAttribute("class", "alert alert-warning");
warn.setAttribute("role", "alert"); warn.setAttribute("role", "alert");
warn.innerHTML = "<h5>Mojang issues</h5> Mojang's servers are having trouble <i>right now</i>, this may affect <b>" + error + "</b> requests at Crafatar. <small><a href=\"https://help.mojang.com\" target=\"_blank\">check status</a>"; warn.innerHTML = "<h5>Mojang issues</h5> Mojang's servers are having trouble <i>right now</i>, this may affect requests at Crafatar. <small><a href=\"https://help.mojang.com\" target=\"_blank\">check status</a>";
document.querySelector("#alerts").appendChild(warn); document.querySelector("#alerts").appendChild(warn);
} }
}; };

View File

@ -79,7 +79,7 @@ module.exports = function(req, callback) {
} else if (!helpers.id_valid(userId)) { } else if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
body: "Invalid UserID", body: "Invalid UUID",
}); });
return; return;
} }

View File

@ -20,7 +20,7 @@ module.exports = function(req, callback) {
if (!helpers.id_valid(userId)) { if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
body: "Invalid UserID" body: "Invalid UUID"
}); });
return; return;
} }

View File

@ -94,7 +94,7 @@ module.exports = function(req, callback) {
} else if (!helpers.id_valid(userId)) { } else if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
body: "Invalid UserID" body: "Invalid UUID"
}); });
return; return;
} }

View File

@ -78,7 +78,7 @@ module.exports = function(req, callback) {
if (!helpers.id_valid(userId)) { if (!helpers.id_valid(userId)) {
callback({ callback({
status: -2, status: -2,
body: "Invalid UserID" body: "Invalid UUID"
}); });
return; return;
} }

View File

@ -128,14 +128,6 @@ exp.resize_img = function(inname, size, callback) {
// returns "mhf_alex" or "mhf_steve" calculated by the +uuid+ // returns "mhf_alex" or "mhf_steve" calculated by the +uuid+
exp.default_skin = function(uuid) { exp.default_skin = function(uuid) {
if (uuid.length <= 16) {
if (uuid.toLowerCase() === "mhf_alex") {
return uuid;
} else {
// we can't get the skin type by username
return "mhf_steve";
}
} else {
// great thanks to Minecrell for research into Minecraft and Java's UUID hashing! // great thanks to Minecrell for research into Minecraft and Java's UUID hashing!
// https://git.io/xJpV // https://git.io/xJpV
// MC uses `uuid.hashCode() & 1` for alex // MC uses `uuid.hashCode() & 1` for alex
@ -147,7 +139,6 @@ exp.default_skin = function(uuid) {
parseInt(uuid[23], 16) ^ parseInt(uuid[23], 16) ^
parseInt(uuid[31], 16); parseInt(uuid[31], 16);
return lsbs_even ? "mhf_alex" : "mhf_steve"; return lsbs_even ? "mhf_alex" : "mhf_steve";
}
}; };
// helper method for opening a skin file from +skinpath+ // helper method for opening a skin file from +skinpath+

View File

@ -4,7 +4,7 @@
<title>Crafatar A blazing fast API for Minecraft faces!</title> <title>Crafatar A blazing fast API for Minecraft faces!</title>
<meta charset="utf-8"> <meta charset="utf-8">
<link rel="icon" sizes="16x16" type="image/png" href="/favicon.png"> <link rel="icon" sizes="16x16" type="image/png" href="/favicon.png">
<%# FIXME: Use CDN %><link rel="stylesheet" href="/stylesheets/bootstrap.min.css"> <link rel="stylesheet" href="/stylesheets/bootstrap.min.css">
<link rel="stylesheet" href="/stylesheets/style.css"> <link rel="stylesheet" href="/stylesheets/style.css">
<meta name="description" content="A blazing fast API for Minecraft faces with support for avatars, skins, and 3D renders!"> <meta name="description" content="A blazing fast API for Minecraft faces with support for avatars, skins, and 3D renders!">
<meta name="keywords" content="minecraft, avatar, renders, skins, uuid"> <meta name="keywords" content="minecraft, avatar, renders, skins, uuid">
@ -62,10 +62,9 @@
<section id="documentation"> <section id="documentation">
<div id="alerts"> <div id="alerts">
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
<h5>Usernames are deprecated!</h5> <h5>Usernames are no longer supported!</h5>
You should only use usernames for <i>testing</i>.<br> Please use UUIDs.
Updates are slower, some features are not available, and it may <strong>break anytime</strong>!<br> <small><a href="#meta-usernames">more info</a></small>
<i>We strongly advise you to use UUIDs instead of usernames.</i> <small><a href="#meta-usernames">more info</a></small>
</div> </div>
</div> </div>
@ -74,7 +73,7 @@
<form id="tryit" action="#"> <form id="tryit" action="#">
<div class="row"> <div class="row">
<div class="col-md-11"> <div class="col-md-11">
<input id="tryname" type="text" placeholder="Enter valid username or UUID"> <input id="tryname" type="text" placeholder="Enter valid UUID">
</div> </div>
<div class="col-md-1"> <div class="col-md-1">
<input type="submit" value="Go!"> <input type="submit" value="Go!">
@ -167,7 +166,6 @@
<section id="meta"> <section id="meta">
<h2><a href="#meta">Meta</a></h2> <h2><a href="#meta">Meta</a></h2>
<p> <p>
In the examples above, you can generally use usernames instead of <mark class="green">uuid</mark>. However, apart from the special cases <code><a href="/renders/body/0?default=MHF_Steve" target="_blank">MHF_Steve</a></code> and <code><a href="/renders/body/0?default=MHF_Alex" target="_blank">MHF_Alex</a></code> this is discouraged as explained below.<br>
You can append <code>.png</code> or any other file extension to the URL path if you like to, but all images are PNG. You can append <code>.png</code> or any other file extension to the URL path if you like to, but all images are PNG.
</p> </p>
@ -193,8 +191,8 @@
<li><b>scale</b>: The scale factor for renders. <code><%= config.renders.min_scale %> - <%= config.renders.max_scale %></code> <li><b>scale</b>: The scale factor for renders. <code><%= config.renders.min_scale %> - <%= config.renders.max_scale %></code>
<li><b>overlay</b>: Apply the <span title="Also known as 'hat' or 'jacket' or 'helm'">overlay</span> to the avatar. Presence of this parameter implies <code>true</code>. This option was previously known as <code>helm</code>. <li><b>overlay</b>: Apply the <span title="Also known as 'hat' or 'jacket' or 'helm'">overlay</span> to the avatar. Presence of this parameter implies <code>true</code>. This option was previously known as <code>helm</code>.
<li> <li>
<b>default</b>: The fallback to be used when the requested image cannot be served. You can use a <span title="Make sure to properly percent-encode this!">custom URL</span> or any <mark class="green">uuid</mark>.<br> <b>default</b>: The fallback to be used when the requested image cannot be served. You can use a <span title="Make sure to properly percent-encode this!">custom URL</span>, any <mark class="green">uuid</mark>, or <code>MHF_Steve</code>/<code>MHF_Alex</code>.<br>
The option defaults to either <code>MHF_Steve</code> or <code>MHF_Alex</code>, depending on the requested UUID. All usernames default to <code>MHF_Steve</code>. The option defaults to either <code>MHF_Steve</code> or <code>MHF_Alex</code>, depending on Minecraft's default for the requested UUID.
</ul> </ul>
</section> </section>
@ -207,13 +205,9 @@
<section id="meta-usernames"> <section id="meta-usernames">
<h3><a href="#meta-usernames">About Usernames</a></h3> <h3><a href="#meta-usernames">About Usernames</a></h3>
<p> <p>
We <strong>strongly</strong> advise you to use UUIDs instead of usernames! UUIDs never change while usernames do.<br> By <a href="https://twitter.com/MojangSupport/status/964511258601865216" target="_blank">disabling</a> a legacy API in 2018, Mojang has made it practically impossible for Crafatar to support usernames. Please use UUIDs instead!
Looking up players by username has officially been deprecated by Mojang ever since UUIDs were introduced.<br>
Crafatar uses a legacy <span title="Mojang interface we get data from">API</span> which updates very slowly to retrieve skins for usernames.<br>
Skins come without any details, including whether a player uses the Alex or Steve skin model.<br>
Additionally, Mojang has stated that this legacy interface may be disabled anytime, causing all requests to fail.
</p> </p>
<p>Malformed usernames are rejected.</p> <p>All usernames are rejected.</p>
</section> </section>
<section id="meta-caching"> <section id="meta-caching">

View File

@ -17,7 +17,7 @@ if [ -z "$host" ] || [ ! -z "$@" ]; then
fi fi
# insert newline after uuids # insert newline after uuids
ids="$(echo | cat 'uuids.txt' - 'usernames.txt')" ids="$(cat 'uuids.txt')"
# `brew install coreutils` on OS X # `brew install coreutils` on OS X
ids="$(shuf <<< "$ids" 2>/dev/null || gshuf <<< "$ids")" ids="$(shuf <<< "$ids" 2>/dev/null || gshuf <<< "$ids")"

View File

@ -23,11 +23,9 @@ var fs = require("fs");
config.server.http_timeout *= 3; config.server.http_timeout *= 3;
var uuids = fs.readFileSync("test/uuids.txt").toString().split(/\r?\n/); var uuids = fs.readFileSync("test/uuids.txt").toString().split(/\r?\n/);
var names = fs.readFileSync("test/usernames.txt").toString().split(/\r?\n/);
// Get a random UUID + name in order to prevent rate limiting // Get a random UUIDto prevent rate limiting
var uuid = uuids[Math.round(Math.random() * (uuids.length - 1))]; var uuid = uuids[Math.round(Math.random() * (uuids.length - 1))];
var name = names[Math.round(Math.random() * (names.length - 1))];
// Let's hope these will never be assigned // Let's hope these will never be assigned
@ -62,13 +60,6 @@ function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min; return Math.floor(Math.random() * (max - min + 1)) + min;
} }
var ids = [
uuid.toLowerCase(),
name.toLowerCase(),
name.toUpperCase(),
uuid.toUpperCase(),
];
describe("Crafatar", function() { describe("Crafatar", function() {
// we might have to make 2 HTTP requests // we might have to make 2 HTTP requests
this.timeout(config.server.http_timeout * 2 + 50); this.timeout(config.server.http_timeout * 2 + 50);
@ -86,10 +77,6 @@ describe("Crafatar", function() {
}); });
describe("UUID/username", function() { describe("UUID/username", function() {
it("empty username is invalid", function(done) {
assert.strictEqual(helpers.id_valid(""), false);
done();
});
it("non-hex uuid is invalid", function(done) { it("non-hex uuid is invalid", function(done) {
assert.strictEqual(helpers.id_valid("g098cb60fa8e427cb299793cbd302c9a"), false); assert.strictEqual(helpers.id_valid("g098cb60fa8e427cb299793cbd302c9a"), false);
done(); done();
@ -98,18 +85,6 @@ describe("Crafatar", function() {
assert.strictEqual(helpers.id_valid(""), false); assert.strictEqual(helpers.id_valid(""), false);
done(); done();
}); });
it("non-alphanumeric username is invalid", function(done) {
assert.strictEqual(helpers.id_valid("usernäme"), false);
done();
});
it("dashed username is invalid", function(done) {
assert.strictEqual(helpers.id_valid("user-name"), false);
done();
});
it(">16 length username is invalid", function(done) {
assert.strictEqual(helpers.id_valid("ThisNameIsTooLong"), false);
done();
});
it("lowercase uuid is valid", function(done) { it("lowercase uuid is valid", function(done) {
assert.strictEqual(helpers.id_valid("0098cb60fa8e427cb299793cbd302c9a"), true); assert.strictEqual(helpers.id_valid("0098cb60fa8e427cb299793cbd302c9a"), true);
done(); done();
@ -122,12 +97,28 @@ describe("Crafatar", function() {
assert.strictEqual(helpers.id_valid("0098cb60-fa8e-427c-b299-793cbd302c9a"), true); assert.strictEqual(helpers.id_valid("0098cb60-fa8e-427c-b299-793cbd302c9a"), true);
done(); done();
}); });
it("16 chars, underscored, capital, numbered username is valid", function(done) { it("username is invalid", function(done) {
assert.strictEqual(helpers.id_valid("__niceUs3rname__"), true); assert.strictEqual(helpers.id_valid("__niceUs3rname__"), false);
done(); done();
}); });
it("1 char username is valid", function(done) { it("username alex is invalid", function(done) {
assert.strictEqual(helpers.id_valid("a"), true); assert.strictEqual(helpers.id_valid("alex"), false);
done();
});
it("username mhf_alex is invalid", function(done) {
assert.strictEqual(helpers.id_valid("mhf_alex"), false);
done();
});
it("username steve is invalid", function(done) {
assert.strictEqual(helpers.id_valid("steve"), false);
done();
});
it("username mhf_steve is invalid", function(done) {
assert.strictEqual(helpers.id_valid("mhf_steve"), false);
done();
});
it(">16 length username is invalid", function(done) {
assert.strictEqual(helpers.id_valid("ThisNameIsTooLong"), false);
done(); done();
}); });
it("should not exist (uuid)", function(done) { it("should not exist (uuid)", function(done) {
@ -138,29 +129,8 @@ describe("Crafatar", function() {
done(); done();
}); });
}); });
it("should not exist (username)", function(done) {
networking.get_username_url(rid(), "Steve", 0, function(err, profile) {
assert.ifError(err);
done();
});
});
}); });
describe("Avatar", function() { describe("Avatar", function() {
it("uuid's account should exist, but skin should not", function(done) {
// profile "Alex" - hoping it'll never have a skin
networking.get_profile(rid(), "ec561538f3fd461daff5086b22154bce", function(err, profile) {
assert.ifError(err);
assert.notStrictEqual(profile, null);
networking.get_uuid_info(profile, "CAPE", function(url) {
assert.strictEqual(url, null);
done();
});
});
});
it("Username should default to MHF_Steve", function(done) {
assert.strictEqual(skins.default_skin("TestUser"), "mhf_steve");
done();
});
for (var a in alex_ids) { for (var a in alex_ids) {
var alexid = alex_ids[a]; var alexid = alex_ids[a];
(function(alex_id) { (function(alex_id) {
@ -190,15 +160,6 @@ describe("Crafatar", function() {
done(); done();
}); });
}); });
it("should time out on username info download", function(done) {
var original_timeout = config.server.http_timeout;
config.server.http_timeout = 1;
networking.get_username_url(rid(), "jomo", 0, function(err, url) {
assert.notStrictEqual(["ETIMEDOUT", "ESOCKETTIMEDOUT"].indexOf(err.code), -1);
config.server.http_timeout = original_timeout;
done();
});
});
it("should time out on skin download", function(done) { it("should time out on skin download", function(done) {
var original_timeout = config.http_timeout; var original_timeout = config.http_timeout;
config.server.http_timeout = 1; config.server.http_timeout = 1;
@ -299,7 +260,7 @@ describe("Crafatar", function() {
}); });
it("should return correct HTTP response for URL encoded URLs", function(done) { it("should return correct HTTP response for URL encoded URLs", function(done) {
var url = "http://localhost:3000/%61%76%61%74%61%72%73/%6a%6f%6d%6f"; // avatars/jomo var url = "http://localhost:3000/%61%76%61%74%61%72%73/%61%65%37%39%35%61%61%38%36%33%32%37%34%30%38%65%39%32%61%62%32%35%63%38%61%35%39%66%33%62%61%31"; // avatars/ae795aa86327408e92ab25c8a59f3ba1
request.get(url, function(error, res, body) { request.get(url, function(error, res, body) {
assert.ifError(error); assert.ifError(error);
assert.strictEqual(res.statusCode, 201); assert.strictEqual(res.statusCode, 201);
@ -312,13 +273,7 @@ describe("Crafatar", function() {
}); });
it("should not fail on simultaneous requests", function(done) { it("should not fail on simultaneous requests", function(done) {
// do not change "constructor" ! var url = "http://localhost:3000/avatars/696a82ce41f44b51aa31b8709b8686f0";
// it's a reserved property name, we're testing for that
var sids = ["696a82ce41f44b51aa31b8709b8686f0", "constructor"];
for (var j in sids) {
var id = sids[j];
var url = "http://localhost:3000/avatars/" + id;
// 10 requests at once // 10 requests at once
var requests = 10; var requests = 10;
var finished = 0; var finished = 0;
@ -343,64 +298,9 @@ describe("Crafatar", function() {
for (var k = 0; k < requests; k++) { for (var k = 0; k < requests; k++) {
req(k); req(k);
} }
}
}); });
var server_tests = { var server_tests = {
"avatar with existing username": {
url: "http://localhost:3000/avatars/jeb_?size=16",
crc32: [3337292777],
},
"avatar with non-existent username": {
url: "http://localhost:3000/avatars/0?size=16",
crc32: [2416827277, 1243826040],
},
"avatar with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/avatars/0?size=16&default=mhf_alex",
crc32: [862751081, 809395677],
},
"avatar with non-existent username defaulting to username": {
url: "http://localhost:3000/avatars/0?size=16&default=jeb_",
crc32: [0],
redirect: "/avatars/jeb_?size=16",
},
"avatar with non-existent username defaulting to uuid": {
url: "http://localhost:3000/avatars/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
},
"avatar with non-existent username defaulting to url": {
url: "http://localhost:3000/avatars/0?size=16&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"overlay avatar with existing username": {
url: "http://localhost:3000/avatars/jeb_?size=16&overlay",
crc32: [1710265722],
},
"overlay avatar with non-existent username": {
url: "http://localhost:3000/avatars/0?size=16&overlay",
crc32: [2416827277, 1243826040],
},
"overlay avatar with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/avatars/0?size=16&overlay&default=mhf_alex",
crc32: [862751081, 809395677],
},
"overlay avatar with non-existent username defaulting to username": {
url: "http://localhost:3000/avatars/0?size=16&overlay&default=jeb_",
crc32: [0],
redirect: "/avatars/jeb_?size=16&overlay=",
},
"overlay avatar with non-existent username defaulting to uuid": {
url: "http://localhost:3000/avatars/0?size=16&overlay&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?size=16&overlay=",
},
"overlay avatar with non-existent username defaulting to url": {
url: "http://localhost:3000/avatars/0?size=16&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"avatar with existing uuid": { "avatar with existing uuid": {
url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16", url: "http://localhost:3000/avatars/853c80ef3c3749fdaa49938b674adae6?size=16",
crc32: [3337292777], crc32: [3337292777],
@ -413,11 +313,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=mhf_alex", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=mhf_alex",
crc32: [862751081, 809395677], crc32: [862751081, 809395677],
}, },
"avatar with non-existent uuid defaulting to username": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
crc32: [0],
redirect: "/avatars/jeb_?size=16",
},
"avatar with non-existent uuid defaulting to uuid": { "avatar with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
@ -440,11 +335,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=mhf_alex", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&overlay&default=mhf_alex",
crc32: [862751081, 809395677], crc32: [862751081, 809395677],
}, },
"overlay avatar with non-existent uuid defaulting to username": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
crc32: [0],
redirect: "/avatars/jeb_?size=16",
},
"overlay avatar with non-existent uuid defaulting to uuid": { "overlay avatar with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
@ -455,19 +345,6 @@ describe("Crafatar", function() {
crc32: [0], crc32: [0],
redirect: "http://example.com/CaseSensitive", redirect: "http://example.com/CaseSensitive",
}, },
"cape with existing username": {
url: "http://localhost:3000/capes/notch",
crc32: [2556702429],
},
"cape with non-existent username": {
url: "http://localhost:3000/capes/0",
crc32: [0],
},
"cape with non-existent username defaulting to url": {
url: "http://localhost:3000/capes/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"cape with existing uuid": { "cape with existing uuid": {
url: "http://localhost:3000/capes/069a79f444e94726a5befca90e38aaf5", url: "http://localhost:3000/capes/069a79f444e94726a5befca90e38aaf5",
crc32: [2556702429], crc32: [2556702429],
@ -481,33 +358,6 @@ describe("Crafatar", function() {
crc32: [0], crc32: [0],
redirect: "http://example.com/CaseSensitive", redirect: "http://example.com/CaseSensitive",
}, },
"skin with existing username": {
url: "http://localhost:3000/skins/jeb_",
crc32: [26500336],
},
"skin with non-existent username": {
url: "http://localhost:3000/skins/0",
crc32: [981937087],
},
"skin with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/skins/0?default=mhf_alex",
crc32: [2298915739],
},
"skin with non-existent username defaulting to username": {
url: "http://localhost:3000/skins/0?size=16&default=jeb_",
crc32: [0],
redirect: "/skins/jeb_?size=16",
},
"skin with non-existent username defaulting to uuid": {
url: "http://localhost:3000/skins/0?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/skins/853c80ef3c3749fdaa49938b674adae6?size=16",
},
"skin with non-existent username defaulting to url": {
url: "http://localhost:3000/skins/0?default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"skin with existing uuid": { "skin with existing uuid": {
url: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/skins/853c80ef3c3749fdaa49938b674adae6",
crc32: [26500336], crc32: [26500336],
@ -520,11 +370,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=mhf_alex", url: "http://localhost:3000/skins/00000000000000000000000000000000?default=mhf_alex",
crc32: [2298915739], crc32: [2298915739],
}, },
"skin with non-existent uuid defaulting to username": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=jeb_",
crc32: [0],
redirect: "/skins/jeb_?size=16",
},
"skin with non-existent uuid defaulting to uuid": { "skin with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
@ -535,60 +380,6 @@ describe("Crafatar", function() {
crc32: [0], crc32: [0],
redirect: "http://example.com/CaseSensitive", redirect: "http://example.com/CaseSensitive",
}, },
"head render with existing username": {
url: "http://localhost:3000/renders/head/jeb_?scale=2",
crc32: [3487896679, 3001090792],
},
"head render with non-existent username": {
url: "http://localhost:3000/renders/head/0?scale=2",
crc32: [3257141069, 214248305],
},
"head render with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/renders/head/0?scale=2&default=mhf_alex",
crc32: [263450586, 3116770561],
},
"head render with non-existent username defaulting to username": {
url: "http://localhost:3000/avatars/0?scale=2&default=jeb_",
crc32: [0],
redirect: "/avatars/jeb_?scale=2",
},
"head render with non-existent username defaulting to uuid": {
url: "http://localhost:3000/avatars/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/avatars/853c80ef3c3749fdaa49938b674adae6?scale=2",
},
"head render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/head/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"overlay head render with existing username": {
url: "http://localhost:3000/renders/head/jeb_?scale=2&overlay",
crc32: [762377383, 1726474987],
},
"overlay head render with non-existent username": {
url: "http://localhost:3000/renders/head/0?scale=2&overlay",
crc32: [3257141069, 214248305],
},
"overlay head render with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=mhf_alex",
crc32: [263450586, 3116770561],
},
"overlay head render with non-existent username defaulting to username": {
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=jeb_",
crc32: [0],
redirect: "/renders/head/jeb_?scale=2&overlay=",
},
"overlay head render with non-existent username defaulting to uuid": {
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay=",
},
"overlay head render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/head/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"head render with existing uuid": { "head render with existing uuid": {
url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2", url: "http://localhost:3000/renders/head/853c80ef3c3749fdaa49938b674adae6?scale=2",
crc32: [3487896679, 3001090792], crc32: [3487896679, 3001090792],
@ -601,11 +392,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=mhf_alex", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=mhf_alex",
crc32: [263450586, 3116770561], crc32: [263450586, 3116770561],
}, },
"head render with non-existent uuid defaulting to username": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=jeb_",
crc32: [0],
redirect: "/renders/head/jeb_?scale=2",
},
"head render with non-existent uuid defaulting to uuid": { "head render with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
@ -628,11 +414,6 @@ describe("Crafatar", function() {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=mhf_alex",
crc32: [263450586, 3116770561], crc32: [263450586, 3116770561],
}, },
"overlay head with non-existent uuid defaulting to username": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=jeb_",
crc32: [0],
redirect: "/renders/head/jeb_?scale=2&overlay=",
},
"overlay head with non-existent uuid defaulting to uuid": { "overlay head with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
@ -643,60 +424,6 @@ describe("Crafatar", function() {
crc32: [0], crc32: [0],
redirect: "http://example.com/CaseSensitive", redirect: "http://example.com/CaseSensitive",
}, },
"body render with existing username": {
url: "http://localhost:3000/renders/body/jeb_?scale=2",
crc32: [3127075871, 2595192206],
},
"body render with non-existent username": {
url: "http://localhost:3000/renders/body/0?scale=2",
crc32: [1046655221, 1620063267],
},
"body render with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/renders/body/0?scale=2&default=mhf_alex",
crc32: [549240598, 3952648540],
},
"body render with non-existent username defaulting to username": {
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
crc32: [0],
redirect: "/renders/body/jeb_?scale=2",
},
"body render with non-existent username defaulting to uuid": {
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
},
"body render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/body/0?scale=2&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"overlay body render with existing username": {
url: "http://localhost:3000/renders/body/jeb_?scale=2&overlay",
crc32: [699892097, 2732138694],
},
"overlay body render with non-existent username": {
url: "http://localhost:3000/renders/body/0?scale=2&overlay",
crc32: [1046655221, 1620063267],
},
"overlay body render with non-existent username defaulting to mhf_alex": {
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=mhf_alex",
crc32: [549240598, 3952648540],
},
"overlay body render with non-existent username defaulting to username": {
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=jeb_",
crc32: [0],
redirect: "/renders/body/jeb_?scale=2&overlay=",
},
"overlay body render with non-existent username defaulting to uuid": {
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0],
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2&overlay=",
},
"overlay body render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/body/0?scale=2&overlay&default=http%3A%2F%2Fexample.com%2FCaseSensitive",
crc32: [0],
redirect: "http://example.com/CaseSensitive",
},
"body render with existing uuid": { "body render with existing uuid": {
url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2", url: "http://localhost:3000/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
crc32: [3127075871, 2595192206], crc32: [3127075871, 2595192206],
@ -709,13 +436,8 @@ describe("Crafatar", function() {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=mhf_alex", url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=mhf_alex",
crc32: [549240598, 3952648540], crc32: [549240598, 3952648540],
}, },
"body render with non-existent uuid defaulting to username": {
url: "http://localhost:3000/renders/body/0?scale=2&default=jeb_",
crc32: [0],
redirect: "/renders/body/jeb_?scale=2",
},
"body render with non-existent uuid defaulting to uuid": { "body render with non-existent uuid defaulting to uuid": {
url: "http://localhost:3000/renders/body/0?scale=2&default=853c80ef3c3749fdaa49938b674adae6", url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=853c80ef3c3749fdaa49938b674adae6",
crc32: [0], crc32: [0],
redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2", redirect: "/renders/body/853c80ef3c3749fdaa49938b674adae6?scale=2",
}, },
@ -784,28 +506,12 @@ describe("Crafatar", function() {
}(loc)); }(loc));
} }
it("should update the username skin type on uuid request", function(done) {
/*eslint-disable handle-callback-err */
request.get("http://localhost:3000/renders/body/mhf_alex", function(error, res, body) {
cache.get_details("mhf_alex", function(err, details) {
assert.strictEqual(details.slim, false);
request.get("http://localhost:3000/renders/body/6ab4317889fd490597f60f67d9d76fd9", function(uerror, ures, ubody) {
cache.get_details("mhf_alex", function(cerr, cdetails) {
/*eslint-enable handle-callback-err */
assert.strictEqual(cdetails.slim, true);
done();
});
});
});
});
});
it("should return 304 on server error", function(done) { it("should return 304 on server error", function(done) {
var original_debug = config.server.debug_enabled; var original_debug = config.server.debug_enabled;
var original_timeout = config.server.http_timeout; var original_timeout = config.server.http_timeout;
config.server.debug_enabled = false; config.server.debug_enabled = false;
config.server.http_timeout = 1; config.server.http_timeout = 1;
request.get({url: "http://localhost:3000/avatars/whatever", headers: {"If-None-Match": '"some-etag"'}}, function(error, res, body) { request.get({url: "http://localhost:3000/avatars/0000000000000000000000000000000f", headers: {"If-None-Match": '"some-etag"'}}, function(error, res, body) {
assert.ifError(error); assert.ifError(error);
assert.ifError(body); assert.ifError(body);
assert.strictEqual(res.statusCode, 304); assert.strictEqual(res.statusCode, 304);
@ -817,7 +523,7 @@ describe("Crafatar", function() {
it("should return a 422 (invalid size)", function(done) { it("should return a 422 (invalid size)", function(done) {
var size = config.avatars.max_size + 1; var size = config.avatars.max_size + 1;
request.get("http://localhost:3000/avatars/Jake_0?size=" + size, function(error, res, body) { request.get("http://localhost:3000/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=" + size, function(error, res, body) {
assert.ifError(error); assert.ifError(error);
assert.strictEqual(res.statusCode, 422); assert.strictEqual(res.statusCode, 422);
done(); done();
@ -826,7 +532,7 @@ describe("Crafatar", function() {
it("should return a 422 (invalid scale)", function(done) { it("should return a 422 (invalid scale)", function(done) {
var scale = config.renders.max_scale + 1; var scale = config.renders.max_scale + 1;
request.get("http://localhost:3000/renders/head/Jake_0?scale=" + scale, function(error, res, body) { request.get("http://localhost:3000/renders/head/2d5aa9cdaeb049189930461fc9b91cc5?scale=" + scale, function(error, res, body) {
assert.ifError(error); assert.ifError(error);
assert.strictEqual(res.statusCode, 422); assert.strictEqual(res.statusCode, 422);
done(); done();
@ -841,12 +547,12 @@ describe("Crafatar", function() {
}); });
}); });
// testing all paths for Invalid UserID // testing all paths for Invalid UUID
var locations = ["avatars", "skins", "capes", "renders/body", "renders/head"]; var locations = ["avatars", "skins", "capes", "renders/body", "renders/head"];
for (var l in locations) { for (var l in locations) {
loc = locations[l]; loc = locations[l];
(function(location) { (function(location) {
it("should return a 422 (invalid id " + location + ")", function(done) { it("should return a 422 (invalid uuid " + location + ")", function(done) {
request.get("http://localhost:3000/" + location + "/thisisaninvaliduuid", function(error, res, body) { request.get("http://localhost:3000/" + location + "/thisisaninvaliduuid", function(error, res, body) {
assert.ifError(error); assert.ifError(error);
assert.strictEqual(res.statusCode, 422); assert.strictEqual(res.statusCode, 422);
@ -873,14 +579,14 @@ describe("Crafatar", function() {
// we have to make sure that we test both a 32x64 and 64x64 skin // we have to make sure that we test both a 32x64 and 64x64 skin
describe("Networking: Render", function() { describe("Networking: Render", function() {
it("should not fail (username, 32x64 skin)", function(done) { it("should not fail (uuid, 32x64 skin)", function(done) {
helpers.get_render(rid(), "md_5", 6, true, true, function(err, hash, img) { helpers.get_render(rid(), "af74a02d19cb445bb07f6866a861f783", 6, true, true, function(err, hash, img) {
assert.strictEqual(err, null); assert.strictEqual(err, null);
done(); done();
}); });
}); });
it("should not fail (username, 64x64 skin)", function(done) { it("should not fail (uuid, 64x64 skin)", function(done) {
helpers.get_render(rid(), "Jake_0", 6, true, true, function(err, hash, img) { helpers.get_render(rid(), "2d5aa9cdaeb049189930461fc9b91cc5", 6, true, true, function(err, hash, img) {
assert.strictEqual(err, null); assert.strictEqual(err, null);
done(); done();
}); });
@ -931,53 +637,30 @@ describe("Crafatar", function() {
}); });
// DRY with uuid and username tests
for (var i in ids) {
var iid = ids[i];
var iid_type = iid.length > 16 ? "uuid" : "name";
// needs an anonymous function because id and id_type aren't constant
(function(n, id, id_type) {
// Mojang's UUID rate limiting is case-insensitive
// so we don't run UUID tests twice
if(n < 3) {
describe("Networking: Avatar", function() { describe("Networking: Avatar", function() {
before(function() { before(function() {
cache.get_redis().flushall(); cache.get_redis().flushall();
console.log("\n\nRunning tests with " + id_type + " '" + id + "'\n\n");
}); });
it("should be downloaded", function(done) { it("should be downloaded", function(done) {
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) { helpers.get_avatar(rid(), uuid, false, 160, function(err, status, image) {
assert.ifError(err); assert.ifError(err);
assert.strictEqual(status, 2); assert.strictEqual(status, 2);
done(); done();
}); });
}); });
it("should be cached", function(done) { it("should be cached", function(done) {
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) { helpers.get_avatar(rid(), uuid, false, 160, function(err, status, image) {
assert.ifError(err); assert.ifError(err);
assert.strictEqual(status === 0 || status === 1, true); assert.strictEqual(status === 0 || status === 1, true);
done(); done();
}); });
}); });
if (id.length > 16) {
// can't run 'checked' test due to Mojang's rate limits :(
} else {
it("should be checked", function(done) {
var original_cache_time = config.caching.local;
config.caching.local = 0;
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
assert.ifError(err);
assert.strictEqual(status, 3);
config.caching.local = original_cache_time;
done();
});
});
}
}); });
describe("Networking: Skin", function() { describe("Networking: Skin", function() {
it("should not fail (uuid)", function(done) { it("should not fail (uuid)", function(done) {
helpers.get_skin(rid(), id, function(err, hash, status, img) { helpers.get_skin(rid(), uuid, function(err, hash, status, img) {
assert.strictEqual(err, null); assert.strictEqual(err, null);
done(); done();
}); });
@ -986,13 +669,13 @@ describe("Crafatar", function() {
describe("Networking: Render", function() { describe("Networking: Render", function() {
it("should not fail (full body)", function(done) { it("should not fail (full body)", function(done) {
helpers.get_render(rid(), id, 6, true, true, function(err, hash, img) { helpers.get_render(rid(), uuid, 6, true, true, function(err, hash, img) {
assert.ifError(err); assert.ifError(err);
done(); done();
}); });
}); });
it("should not fail (only head)", function(done) { it("should not fail (only head)", function(done) {
helpers.get_render(rid(), id, 6, true, false, function(err, hash, img) { helpers.get_render(rid(), uuid, 6, true, false, function(err, hash, img) {
assert.ifError(err); assert.ifError(err);
done(); done();
}); });
@ -1001,46 +684,27 @@ describe("Crafatar", function() {
describe("Networking: Cape", function() { describe("Networking: Cape", function() {
it("should not fail (possible cape)", function(done) { it("should not fail (possible cape)", function(done) {
helpers.get_cape(rid(), id, function(err, hash, status, img) { helpers.get_cape(rid(), uuid, function(err, hash, status, img) {
assert.ifError(err); assert.ifError(err);
done(); done();
}); });
}); });
}); });
}
describe("Errors", function() { describe("Errors", function() {
before(function() { before(function() {
if(n >= 3) {
// Notice for tests skipped above
console.log("\n\nSkipping tests with " + id_type + " '" + id + "' due to case-insensitive rate-limiting\n\n");
}
cache.get_redis().flushall(); cache.get_redis().flushall();
}); });
if (id_type === "uuid") {
// just making sure ...
it("uuid SHOULD be rate limited", function(done) { it("uuid SHOULD be rate limited", function(done) {
networking.get_profile(rid(), id, function() { networking.get_profile(rid(), uuid, function() {
networking.get_profile(rid(), id, function(err, profile) { networking.get_profile(rid(), uuid, function(err, profile) {
assert.strictEqual(err.toString(), "HTTP: 429"); assert.strictEqual(err.toString(), "HTTP: 429");
assert.strictEqual(profile, null); assert.strictEqual(profile, null);
done(); done();
}); });
}); });
}); });
} else {
it("username should NOT be rate limited (username)", function(done) {
helpers.get_avatar(rid(), id, false, 160, function() {
helpers.get_avatar(rid(), id, false, 160, function(err, status, image) {
assert.strictEqual(err, null);
done();
}); });
}); });
});
}
});
}(i, iid, iid_type));
}
});