Namespace and move config to root directory, closes #124

This commit is contained in:
Jake 2015-06-25 13:12:08 -05:00
parent 2eb1112c3b
commit a2e0edc491
16 changed files with 210 additions and 101 deletions

37
config.example.js Normal file
View File

@ -0,0 +1,37 @@
var config = {
avatars: {
min_size: 1, // for avatars
max_size: 512, // for avatars; too big values might lead to slow response time or DoS
default_size: 160 // for avatars; size to be used when no size given
},
renders: {
min_scale: 1, // for 3D renders
max_scale: 10, // for 3D renders; too big values might lead to slow response time or DoS
default_scale: 6 // for 3D renders; scale to be used when no scale given
},
cleaner: {
interval: 1800, // seconds interval: deleting images if disk size at limit
disk_limit: 10240, // min allowed available KB on disk to trigger cleaning
redis_limit: 24576, // max allowed used KB on redis to trigger redis flush
amount: 50000 // amount of avatar (and their helm) files to clean
},
directories: {
faces_dir: "images/faces/", // directory where faces are kept. should have trailing "/"
helms_dir: "images/helms/", // directory where helms are kept. should have trailing "/"
skins_dir: "images/skins/", // directory where skins are kept. should have trailing "/"
renders_dir: "images/renders/", // Directory where rendered skins are kept. should have trailing "/"
capes_dir: "images/capes/" // directory where capes are kept. should have trailing "/"
},
caching: {
local_cache_time: 1200, // seconds until we will check if the image changed. should be > 60 to prevent mojang 429 response
browser_cache_time: 3600 // seconds until browser will request image again
},
server: {
http_timeout: 1000, // ms until connection to mojang is dropped
debug_enabled: false, // enables logging.debug
clusters: 1, // We recommend not using multiple clusters YET, see issue #80
log_time: true // set to false if you use an external logger that provides timestamps
}
};
module.exports = config;

37
config.js Normal file
View File

@ -0,0 +1,37 @@
var config = {
avatars: {
min_size: 1, // for avatars
max_size: 512, // for avatars; too big values might lead to slow response time or DoS
default_size: 160 // for avatars; size to be used when no size given
},
renders: {
min_scale: 1, // for 3D renders
max_scale: 10, // for 3D renders; too big values might lead to slow response time or DoS
default_scale: 6 // for 3D renders; scale to be used when no scale given
},
cleaner: {
interval: 1800, // seconds interval: deleting images if disk size at limit
disk_limit: 10240, // min allowed available KB on disk to trigger cleaning
redis_limit: 24576, // max allowed used KB on redis to trigger redis flush
amount: 50000 // amount of avatar (and their helm) files to clean
},
directories: {
faces_dir: "images/faces/", // directory where faces are kept. should have trailing "/"
helms_dir: "images/helms/", // directory where helms are kept. should have trailing "/"
skins_dir: "images/skins/", // directory where skins are kept. should have trailing "/"
renders_dir: "images/renders/", // Directory where rendered skins are kept. should have trailing "/"
capes_dir: "images/capes/" // directory where capes are kept. should have trailing "/"
},
caching: {
local_cache_time: 1200, // seconds until we will check if the image changed. should be > 60 to prevent mojang 429 response
browser_cache_time: 3600 // seconds until browser will request image again
},
server: {
http_timeout: 1000, // ms until connection to mojang is dropped
debug_enabled: false, // enables logging.debug
clusters: 1, // We recommend not using multiple clusters YET, see issue #80
log_time: true // set to false if you use an external logger that provides timestamps
}
};
module.exports = config;

View File

@ -1,6 +1,6 @@
var logging = require("./logging");
var node_redis = require("redis");
var config = require("./config");
var config = require("../config");
var path = require("path");
var url = require("url");
var fs = require("fs");
@ -40,7 +40,7 @@ function connect_redis() {
// the helms file is ignored because we only need 1 file to read/write from
function update_file_date(rid, skin_hash) {
if (skin_hash) {
var face_path = path.join(__dirname, "..", config.faces_dir, skin_hash + ".png");
var face_path = path.join(__dirname, "..", config.directories.faces_dir, skin_hash + ".png");
fs.exists(face_path, function(exists) {
if (exists) {
var date = new Date();
@ -99,7 +99,7 @@ exp.info = function(callback) {
// callback: error
exp.update_timestamp = function(rid, userId, hash, temp, callback) {
logging.debug(rid, "updating cache timestamp");
var sub = temp ? (config.local_cache_time - 60) : 0;
var sub = temp ? (config.caching.local_cache_time - 60) : 0;
var time = Date.now() - sub;
// store userId in lower case if not null
userId = userId && userId.toLowerCase();

View File

@ -1,5 +1,5 @@
var logging = require("./logging");
var config = require("./config");
var config = require("../config");
var cache = require("./cache");
var path = require("path");
var df = require("node-df");
@ -23,7 +23,7 @@ function should_clean_redis(callback) {
logging.debug("used mem:" + info.used_memory);
var used = parseInt(info.used_memory) / 1024;
logging.log("RedisCleaner:", used + "KB used");
callback(err, used >= config.cleaning_redis_limit);
callback(err, used >= config.cleaner.redis_limit);
} catch(e) {
callback(e, false);
}
@ -35,7 +35,7 @@ function should_clean_redis(callback) {
// callback: error, true|false
function should_clean_disk(callback) {
df({
file: path.join(__dirname, "..", config.faces_dir),
file: path.join(__dirname, "..", config.directories.faces_dir),
prefixMultiplier: "KiB",
isDisplayPrefixMultiplier: false,
precision: 2
@ -45,7 +45,7 @@ function should_clean_disk(callback) {
} else {
var available = response[0].available;
logging.log("DiskCleaner:", available + "KB available");
callback(err, available < config.cleaning_disk_limit);
callback(err, available < config.cleaner.disk_limit);
}
});
}
@ -71,13 +71,13 @@ exp.run = function() {
logging.error(err);
} else if (clean) {
logging.warn("DiskCleaner: Disk limit reached! Cleaning images now");
var facesdir = path.join(__dirname, "..", config.faces_dir);
var helmdir = path.join(__dirname, "..", config.helms_dir);
var renderdir = path.join(__dirname, "..", config.renders_dir);
var skindir = path.join(__dirname, "..", config.skins_dir);
var facesdir = path.join(__dirname, "..", config.directories.faces_dir);
var helmdir = path.join(__dirname, "..", config.directories.helms_dir);
var renderdir = path.join(__dirname, "..", config.directories.renders_dir);
var skindir = path.join(__dirname, "..", config.directories.skins_dir);
fs.readdir(facesdir, function (readerr, files) {
if (!readerr) {
for (var i = 0, l = Math.min(files.length, config.cleaning_amount); i < l; i++) {
for (var i = 0, l = Math.min(files.length, config.cleaner.amount); i < l; i++) {
var filename = files[i];
if (filename[0] !== ".") {
fs.unlink(path.join(facesdir, filename), nil);
@ -89,7 +89,7 @@ exp.run = function() {
});
fs.readdir(renderdir, function (readerr, files) {
if (!readerr) {
for (var j = 0, l = Math.min(files.length, config.cleaning_amount); j < l; j++) {
for (var j = 0, l = Math.min(files.length, config.cleaner.amount); j < l; j++) {
var filename = files[j];
if (filename[0] !== ".") {
fs.unlink(renderdir + filename, nil);

View File

@ -1,25 +0,0 @@
var config = {
min_size: 1, // for avatars
max_size: 512, // for avatars; too big values might lead to slow response time or DoS
default_size: 160, // for avatars; size to be used when no size given
min_scale: 1, // for 3D renders
max_scale: 10, // for 3D renders; too big values might lead to slow response time or DoS
default_scale: 6, // for 3D renders; scale to be used when no scale given
local_cache_time: 1200, // seconds until we will check if the image changed. should be > 60 to prevent mojang 429 response
browser_cache_time: 3600, // seconds until browser will request image again
cleaning_interval: 1800, // seconds interval: deleting images if disk size at limit
cleaning_disk_limit: 10240, // min allowed available KB on disk to trigger cleaning
cleaning_redis_limit: 24576, // max allowed used KB on redis to trigger redis flush
cleaning_amount: 50000, // amount of avatar (and their helm) files to clean
http_timeout: 1000, // ms until connection to mojang is dropped
debug_enabled: false, // enables logging.debug
faces_dir: "images/faces/", // directory where faces are kept. should have trailing "/"
helms_dir: "images/helms/", // directory where helms are kept. should have trailing "/"
skins_dir: "images/skins/", // directory where skins are kept. should have trailing "/"
renders_dir: "images/renders/", // Directory where rendered skins are kept. should have trailing "/"
capes_dir: "images/capes/", // directory where capes are kept. should have trailing "/"
clusters: 1, // We recommend not using multiple clusters YET, see issue #80
log_time: true, // set to false if you use an external logger that provides timestamps
};
module.exports = config;

View File

@ -1,7 +1,7 @@
var networking = require("./networking");
var logging = require("./logging");
var renders = require("./renders");
var config = require("./config");
var config = require("../config");
var cache = require("./cache");
var skins = require("./skins");
var path = require("path");
@ -30,9 +30,9 @@ function store_skin(rid, userId, profile, cache_details, callback) {
});
} else {
logging.log(rid, "new skin hash:", skin_hash);
var facepath = path.join(__dirname, "..", config.faces_dir, skin_hash + ".png");
var helmpath = path.join(__dirname, "..", config.helms_dir, skin_hash + ".png");
var skinpath = path.join(__dirname, "..", config.skins_dir, skin_hash + ".png");
var facepath = path.join(__dirname, "..", config.directories.faces_dir, skin_hash + ".png");
var helmpath = path.join(__dirname, "..", config.directories.helms_dir, skin_hash + ".png");
var skinpath = path.join(__dirname, "..", config.directories.skins_dir, skin_hash + ".png");
fs.exists(facepath, function(exists) {
if (exists) {
logging.log(rid, "skin already exists, not downloading");
@ -87,7 +87,7 @@ function store_cape(rid, userId, profile, cache_details, callback) {
});
} else {
logging.log(rid, "new cape hash:", cape_hash);
var capepath = path.join(__dirname, "..", config.capes_dir, cape_hash + ".png");
var capepath = path.join(__dirname, "..", config.directories.capes_dir, cape_hash + ".png");
fs.exists(capepath, function(exists) {
if (exists) {
logging.log(rid, "cape already exists, not downloading");
@ -223,7 +223,7 @@ exp.get_image_hash = function(rid, userId, type, callback) {
if (err) {
callback(err, -1, null);
} else {
if (cache_details && cache_details[type] !== undefined && cache_details.time + config.local_cache_time * 1000 >= Date.now()) {
if (cache_details && cache_details[type] !== undefined && cache_details.time + config.caching.local_cache_time * 1000 >= Date.now()) {
// use cached image
logging.log(rid, "userId cached & recently updated");
callback(null, (cached_hash ? 1 : 0), cached_hash);
@ -261,8 +261,8 @@ exp.get_image_hash = function(rid, userId, type, callback) {
exp.get_avatar = function(rid, userId, helm, size, callback) {
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) {
if (skin_hash) {
var facepath = path.join(__dirname, "..", config.faces_dir, skin_hash + ".png");
var helmpath = path.join(__dirname, "..", config.helms_dir, skin_hash + ".png");
var facepath = path.join(__dirname, "..", config.directories.faces_dir, skin_hash + ".png");
var helmpath = path.join(__dirname, "..", config.directories.helms_dir, skin_hash + ".png");
var filepath = facepath;
fs.exists(helmpath, function(exists) {
if (helm && exists) {
@ -288,7 +288,7 @@ exp.get_avatar = function(rid, userId, helm, size, callback) {
exp.get_skin = function(rid, userId, callback) {
exp.get_image_hash(rid, userId, "skin", function(err, status, skin_hash) {
if (skin_hash) {
var skinpath = path.join(__dirname, "..", config.skins_dir, skin_hash + ".png");
var skinpath = path.join(__dirname, "..", config.directories.skins_dir, skin_hash + ".png");
fs.exists(skinpath, function(exists) {
if (exists) {
logging.log(rid, "skin already exists, not downloading");
@ -323,7 +323,7 @@ exp.get_render = function(rid, userId, scale, helm, body, callback) {
callback(err, status, skin_hash, null);
return;
}
var renderpath = path.join(__dirname, "..", config.renders_dir, [skin_hash, scale, get_type(helm, body)].join("-") + ".png");
var renderpath = path.join(__dirname, "..", config.directories.renders_dir, [skin_hash, scale, get_type(helm, body)].join("-") + ".png");
fs.exists(renderpath, function(exists) {
if (exists) {
renders.open_render(rid, renderpath, function(render_err, rendered_img) {
@ -362,7 +362,7 @@ exp.get_cape = function(rid, userId, callback) {
callback(err, null, status, null);
return;
}
var capepath = path.join(__dirname, "..", config.capes_dir, cape_hash + ".png");
var capepath = path.join(__dirname, "..", config.directories.capes_dir, cape_hash + ".png");
fs.exists(capepath, function(exists) {
if (exists) {
logging.log(rid, "cape already exists, not downloading");

View File

@ -1,5 +1,5 @@
var cluster = require("cluster");
var config = require("./config");
var config = require("../config");
var exp = {};
@ -17,7 +17,7 @@ function join_args(args) {
// the timestamp can be disabled in the config
function log(level, args, logger) {
logger = logger || console.log;
var time = config.log_time ? new Date().toISOString() + " " : "";
var time = config.server.log_time ? new Date().toISOString() + " " : "";
var clid = (cluster.worker && cluster.worker.id || "M");
var lines = join_args(args).split("\n");
for (var i = 0, l = lines.length; i < l; i++) {
@ -34,7 +34,7 @@ exp.warn = function() {
exp.error = function() {
log("ERROR", arguments, console.error);
};
if (config.debug_enabled || process.env.DEBUG === "true") {
if (config.server.debug_enabled || process.env.DEBUG === "true") {
exp.debug = function() {
log("DEBUG", arguments);
};

View File

@ -1,7 +1,7 @@
var http_code = require("http").STATUS_CODES;
var logging = require("./logging");
var request = require("request");
var config = require("./config");
var config = require("../config");
var skins = require("./skins");
var session_url = "https://sessionserver.mojang.com/session/minecraft/profile/";
@ -67,7 +67,7 @@ exp.get_from_options = function(rid, url, options, callback) {
headers: {
"User-Agent": "https://crafatar.com"
},
timeout: config.http_timeout,
timeout: config.server.http_timeout,
followRedirect: false,
encoding: (options.encoding || null),
}, function(error, response, body) {

View File

@ -1,5 +1,5 @@
var logging = require("./logging");
var config = require("./config");
var config = require("../config");
var crc = require("crc").crc32;
var human_status = {
@ -39,7 +39,7 @@ module.exports = function(request, response, result) {
// These headers are the same for every response
var headers = {
"Content-Type": (result.body && result.type) || "text/plain",
"Cache-Control": "max-age=" + config.browser_cache_time + ", public",
"Cache-Control": "max-age=" + config.caching.browser_cache_time + ", public",
"Response-Time": Date.now() - request.start,
"X-Request-ID": request.id,
"Access-Control-Allow-Origin": "*"

View File

@ -1,6 +1,6 @@
var logging = require("../logging");
var helpers = require("../helpers");
var config = require("../config");
var config = require("../../config");
var skins = require("../skins");
var cache = require("../cache");
var path = require("path");
@ -45,7 +45,7 @@ function handle_default(img_status, userId, size, def, req, err, callback) {
// GET avatar request
module.exports = function(req, callback) {
var userId = (req.url.path_list[1] || "").split(".")[0];
var size = parseInt(req.url.query.size) || config.default_size;
var size = parseInt(req.url.query.size) || config.avatars.default_size;
var def = req.url.query.default;
var helm = req.url.query.hasOwnProperty("helm");
@ -59,7 +59,7 @@ module.exports = function(req, callback) {
}
// Prevent app from crashing/freezing
if (size < config.min_size || size > config.max_size) {
if (size < config.avatars.min_size || size > config.avatars.max_size) {
// "Unprocessable Entity", valid request, but semantically erroneous:
// https://tools.ietf.org/html/rfc4918#page-78
callback({

View File

@ -1,4 +1,4 @@
var config = require("../config");
var config = require("../../config");
var path = require("path");
var jade = require("jade");

View File

@ -1,7 +1,7 @@
var logging = require("../logging");
var helpers = require("../helpers");
var renders = require("../renders");
var config = require("../config");
var config = require("../../config");
var cache = require("../cache");
var skins = require("../skins");
var path = require("path");
@ -9,8 +9,6 @@ var fs = require("fs");
// valid types: head, body
// helmet is query param
// TODO: The Type logic should be two separate GET functions once response methods are extracted
function handle_default(rid, scale, helm, body, img_status, userId, size, def, req, err, callback) {
def = def || skins.default_skin(userId);
if (def !== "steve" && def !== "alex") {
@ -57,7 +55,7 @@ module.exports = function(req, callback) {
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 scale = parseInt(req.url.query.scale) || config.renders.default_scale;
var helm = req.url.query.hasOwnProperty("helm");
// check for extra paths
@ -78,7 +76,7 @@ module.exports = function(req, callback) {
return;
}
if (scale < config.min_scale || scale > config.max_scale) {
if (scale < config.renders.min_scale || scale > config.renders.max_scale) {
callback({
status: -2,
body: "Invalid Scale"

View File

@ -3,7 +3,7 @@ var querystring = require("querystring");
var response = require("./response");
var toobusy = require("toobusy-js");
var logging = require("./logging");
var config = require("./config");
var config = require("../config");
var http = require("http");
var mime = require("mime");
var path = require("path");
@ -116,7 +116,7 @@ function requestHandler(req, res) {
res.writeHead(500, {
"Content-Type": "text/plain"
});
res.end(config.debug_enabled ? error : "Internal Server Error");
res.end(config.server.debug_enabled ? error : "Internal Server Error");
}
} else {
res.writeHead(405, {

View File

@ -56,8 +56,8 @@ block content
tr
td size
td integer
td #{config.default_size}
td The size of the image in pixels, #{config.min_size} - #{config.max_size}.
td #{config.avatars.default_size}
td The size of the image in pixels, #{config.avatars.min_size} - #{config.avatars.max_size}.
tr
td default
td string
@ -140,8 +140,8 @@ block content
tr
td scale
td integer
td #{config.default_scale}. The actual size differs between the type of render.
td The scale factor of the image #{config.min_scale} - #{config.max_scale}.
td #{config.renders.default_scale}. The actual size differs between the type of render.
td The scale factor of the image #{config.renders.min_scale} - #{config.renders.max_scale}.
tr
td helm
td null
@ -324,8 +324,8 @@ block content
a(href="#meta-about-caching")
h3 About Caching
p
| Crafatar caches skins for #{config.local_cache_time/60} minutes before checking for skin changes.<br>
| Images are cached in your browser for #{config.browser_cache_time/60} minutes until a new request to Crafatar is made.<br>
| Crafatar caches skins for #{config.caching.local_cache_time/60} minutes before checking for skin changes.<br>
| Images are cached in your browser for #{config.caching.browser_cache_time/60} minutes until a new request to Crafatar is made.<br>
| When you changed your skin you can try clearing your browser cache to see the change faster.

View File

@ -5,7 +5,7 @@ var helpers = require("../lib/helpers");
var logging = require("../lib/logging");
var cleaner = require("../lib/cleaner");
var request = require("request");
var config = require("../lib/config");
var config = require("../config");
var server = require("../lib/server");
var assert = require("assert");
var skins = require("../lib/skins");
@ -14,7 +14,7 @@ var crc = require("crc").crc32;
var fs = require("fs");
// we don't want tests to fail because of slow internet
config.http_timeout *= 3;
config.server.http_timeout *= 3;
// no spam
if (process.env.VERBOSE_TEST !== "true") {
@ -67,13 +67,13 @@ var ids = [
describe("Crafatar", function() {
// we might have to make 2 HTTP requests
this.timeout(config.http_timeout * 2 + 50);
this.timeout(config.server.http_timeout * 2 + 50);
before(function() {
cache.get_redis().flushall();
// cause I don't know how big hard drives are these days
config.cleaning_disk_limit = Infinity;
config.cleaning_redis_limit = Infinity;
config.cleaner.disk_limit = Infinity;
config.cleaner.redis_limit = Infinity;
cleaner.run();
});
@ -170,29 +170,29 @@ describe("Crafatar", function() {
});
describe("Errors", function() {
it("should time out on uuid info download", function(done) {
var original_timeout = config.http_timeout;
config.http_timeout = 1;
var original_timeout = config.server.http_timeout;
config.server.http_timeout = 1;
networking.get_profile(rid, "069a79f444e94726a5befca90e38aaf5", function(err, profile) {
assert.strictEqual(err.code, "ETIMEDOUT");
config.http_timeout = original_timeout;
config.server.http_timeout = original_timeout;
done();
});
});
it("should time out on username info download", function(done) {
var original_timeout = config.http_timeout;
config.http_timeout = 1;
var original_timeout = config.server.http_timeout;
config.server.http_timeout = 1;
networking.get_username_url(rid, "jomo", 0, function(err, url) {
assert.strictEqual(err.code, "ETIMEDOUT");
config.http_timeout = original_timeout;
config.server.http_timeout = original_timeout;
done();
});
});
it("should time out on skin download", function(done) {
var original_timeout = config.http_timeout;
config.http_timeout = 1;
config.server.http_timeout = 1;
networking.get_from(rid, "http://textures.minecraft.net/texture/477be35554684c28bdeee4cf11c591d3c88afb77e0b98da893fd7bc318c65184", function(body, res, error) {
assert.strictEqual(error.code, "ETIMEDOUT");
config.http_timeout = original_timeout;
config.server.http_timeout = original_timeout;
done();
});
});
@ -227,7 +227,7 @@ describe("Crafatar", function() {
assert("" + res.headers["response-time"]);
assert(res.headers["x-request-id"]);
assert.equal(res.headers["access-control-allow-origin"], "*");
assert.equal(res.headers["cache-control"], "max-age=" + config.browser_cache_time + ", public");
assert.equal(res.headers["cache-control"], "max-age=" + config.caching.browser_cache_time + ", public");
}
// throws Exception when +url+ is requested with +etag+
@ -352,6 +352,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [862751081, 809395677]
},
"avatar with non-existent username defaulting to userId": {
url: "http://localhost:3000/avatars/0?size=16&default=jeb_",
crc32: 0,
redirect: "/avatars/jeb_?size=16"
},
"avatar with non-existent username defaulting to url": {
url: "http://localhost:3000/avatars/0?size=16&default=http://example.com",
crc32: 0,
@ -372,6 +377,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [862751081, 809395677]
},
"helm avatar with non-existent username defaulting to userId": {
url: "http://localhost:3000/avatars/0?size=16&helm&default=jeb_",
crc32: 0,
redirect: "/avatars/jeb_?size=16&helm="
},
"helm avatar with non-existent username defaulting to url": {
url: "http://localhost:3000/avatars/0?size=16&helm&default=http://example.com",
crc32: 0,
@ -392,6 +402,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [862751081, 809395677]
},
"avatar with non-existent uuid defaulting to userId": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
crc32: 0,
redirect: "/avatars/jeb_?size=16"
},
"avatar with non-existent uuid defaulting to url": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=http://example.com",
crc32: 0,
@ -412,6 +427,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [862751081, 809395677]
},
"helm avatar with non-existent uuid defaulting to userId": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&default=jeb_",
crc32: 0,
redirect: "/avatars/jeb_?size=16"
},
"helm avatar with non-existent uuid defaulting to url": {
url: "http://localhost:3000/avatars/00000000000000000000000000000000?size=16&helm&default=http://example.com",
crc32: 0,
@ -460,6 +480,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: 2298915739
},
"skin with non-existent username defaulting to userId": {
url: "http://localhost:3000/skins/0?size=16&default=jeb_",
crc32: 0,
redirect: "/skins/jeb_?size=16"
},
"skin with non-existent username defaulting to url": {
url: "http://localhost:3000/skins/0?default=http://example.com",
crc32: 0,
@ -480,11 +505,18 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: 2298915739
},
"skin with non-existent uuid defaulting to userId": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?size=16&default=jeb_",
crc32: 0,
redirect: "/skins/jeb_?size=16"
},
"skin with non-existent uuid defaulting to url": {
url: "http://localhost:3000/skins/00000000000000000000000000000000?default=http://example.com",
crc32: 0,
redirect: "http://example.com"
},
"head render with existing username": {
url: "http://localhost:3000/renders/head/jeb_?scale=2",
etag: '"a846b82963"',
@ -500,6 +532,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [1240086237, 1108800327]
},
"head render with non-existent useranme defaulting to userId": {
url: "http://localhost:3000/avatars/0?scale=2&default=jeb_",
crc32: 0,
redirect: "/renders/head/jeb_?scale=2"
},
"head render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/head/0?scale=2&default=http://example.com",
crc32: 0,
@ -520,6 +557,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [2963161105, 1769904825]
},
"helm head render with non-existent username defaulting to userId": {
url: "http://localhost:3000/renders/head/0?scale=2&helm&default=jeb_",
crc32: 0,
redirect: "/renders/head/jeb_?scale=2&helm="
},
"helm head render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/head/0?scale=2&helm&default=http://example.com",
crc32: 0,
@ -540,6 +582,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [1240086237, 1108800327]
},
"head render with non-existent uuid defaulting to userId": {
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 url": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&default=http://example.com",
crc32: 0,
@ -560,6 +607,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [2963161105, 1769904825]
},
"helm head with non-existent uuid defaulting to userId": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&helm&default=jeb_",
crc32: 0,
redirect: "/renders/head/jeb_?scale=2&helm="
},
"helm head render with non-existent uuid defaulting to url": {
url: "http://localhost:3000/renders/head/00000000000000000000000000000000?scale=2&helm&default=http://example.com",
crc32: 0,
@ -580,6 +632,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [407932087, 2516216042]
},
"body render with non-existent username defaulting to userId": {
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 url": {
url: "http://localhost:3000/renders/body/0?scale=2&default=http://example.com",
crc32: 0,
@ -600,6 +657,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [737759773, 66512449]
},
"helm body render with non-existent username defaulting to userId": {
url: "http://localhost:3000/renders/body/0?scale=2&helm&default=jeb_",
crc32: 0,
redirect: "/renders/body/jeb_?scale=2&helm="
},
"helm body render with non-existent username defaulting to url": {
url: "http://localhost:3000/renders/body/0?scale=2&helm&default=http://example.com",
crc32: 0,
@ -620,6 +682,11 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [407932087, 2516216042]
},
"body render with non-existent uuid defaulting to userId": {
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 url": {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&default=http://example.com",
crc32: 0,
@ -640,11 +707,6 @@ describe("Crafatar", function() {
etag: '"alex"',
crc32: [737759773, 66512449]
},
"helm body render with non-existent uuid defaulting to userId": {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&helm&default=alex",
etag: '"alex"',
crc32: [737759773, 66512449]
},
"helm body render with non-existent uuid defaulting to url": {
url: "http://localhost:3000/renders/body/00000000000000000000000000000000?scale=2&helm&default=http://example.com",
crc32: 0,
@ -696,7 +758,7 @@ describe("Crafatar", function() {
}
it("should return a 422 (invalid size)", function(done) {
var size = config.max_size + 1;
var size = config.avatars.max_size + 1;
request.get("http://localhost:3000/avatars/Jake_0?size=" + size, function(error, res, body) {
assert.ifError(error);
assert.strictEqual(res.statusCode, 422);
@ -705,7 +767,7 @@ describe("Crafatar", function() {
});
it("should return a 422 (invalid scale)", function(done) {
var scale = config.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) {
assert.ifError(error);
assert.strictEqual(res.statusCode, 422);
@ -833,12 +895,12 @@ describe("Crafatar", function() {
console.log("can't run 'checked' test due to Mojang's rate limits :(");
} else {
it("should be checked", function(done) {
var original_cache_time = config.local_cache_time;
config.local_cache_time = 0;
var original_cache_time = config.caching.local_cache_time;
config.caching.local_cache_time = 0;
helpers.get_avatar(rid, id, false, 160, function(err, status, image) {
assert.ifError(err);
assert.strictEqual(status, 3);
config.local_cache_time = original_cache_time;
config.caching.local_cache_time = original_cache_time;
done();
});
});

8
www.js
View File

@ -1,6 +1,6 @@
var logging = require("./lib/logging");
var cleaner = require("./lib/cleaner");
var config = require("./lib/config");
var config = require("./config");
var cluster = require("cluster");
process.on("uncaughtException", function (err) {
@ -8,8 +8,8 @@ process.on("uncaughtException", function (err) {
});
if (cluster.isMaster) {
var cores = config.clusters || require("os").cpus().length;
logging.log("Starting", cores + " workers");
var cores = config.server.clusters || require("os").cpus().length;
logging.log("Starting", cores + " worker" + (cores > 1 ? "s" : ""));
for (var i = 0; i < cores; i++) {
cluster.fork();
}
@ -19,7 +19,7 @@ if (cluster.isMaster) {
setTimeout(cluster.fork, 100);
});
setInterval(cleaner.run, config.cleaning_interval * 1000);
setInterval(cleaner.run, config.cleaner.interval * 1000);
} else {
require("./lib/server.js").boot();
}