'use strict'; module.exports.create = function (defaults) { var handlers = { getOptions: function () { return defaults; } // // set,get,remove challenges // // Note: this is fine for a one-off CLI tool // but a webserver using node-cluster or multiple // servers should use a database of some sort , _challenges: {} , set: function (args, domain, token, secret, cb) { handlers._challenges[token] = secret; cb(null); } , get: function (args, domain, token, cb) { // TODO keep in mind that, generally get args are just args.domains // and it is disconnected from the flow of setChallenge and removeChallenge cb(null, handlers._challenges[token]); } , remove: function (args, domain, token, cb) { delete handlers._challenges[token]; cb(null); } , loopback: function (defaults, domain, challenge, done) { var hostname = domain + (defaults.loopbackPort ? ':' + defaults.loopbackPort : ''); var urlstr = 'http://' + hostname + '/.well-known/acme-challenge/' + key; require('http').get(urlstr, function (res) { if (200 !== res.statusCode) { done(new Error("local loopback failed with statusCode " + res.statusCode)); return; } var chunks = []; res.on('data', function (chunk) { chunks.push(chunk); }); res.on('end', function () { var str = Buffer.concat(chunks).toString('utf8').trim(); done(null, str); }); }).setTimeout(defaults.loopbackTimeout, function () { done(new Error("loopback timeout, could not reach server")); }).on('error', function (err) { done(err); }); } , test: function (args, domain, challenge, keyAuthorization, done) { var me = this; var key = keyAuthorization || challenge; me.set(args, domain, challenge, key, function (err) { if (err) { done(err); return; } myDefaults.loopbackPort = args.loopbackPort; myDefaults.webrootPath = args.webrootPath; me.loopback(args, domain, challenge, function (err, _key) { if (err) { done(err); return; } if (key !== _key) { err = new Error("keyAuthorization [original] '" + key + "'" + " did not match [result] '" + _key + "'"); return; } me.remove(myDefaults, domain, challenge, function (_err) { if (_err) { done(_err); return; } done(err); }); }); }); } }; return handlers; };