From ccd525a09abdeba7f9756362717b7820d6d009b1 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 12 Oct 2016 16:25:17 -0600 Subject: [PATCH] added loopback test --- index.js | 56 +++++++++++++++++++++++++++++++++++++++++++++++++--- package.json | 4 ++++ test.js | 42 ++++++++++++++++++++++++++++----------- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index 3c8086c..5d29e77 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ var fs = require('fs'); var path = require('path'); -var defaults = { +var myDefaults = { //webrootPath: [ '~', 'letsencrypt', 'var', 'lib' ].join(path.sep) webrootPath: path.join(require('os').tmpdir(), 'acme-challenge') , debug: false @@ -19,9 +19,9 @@ Challenge.create = function (options) { }); results.create = undefined; - Object.keys(defaults).forEach(function (key) { + Object.keys(myDefaults).forEach(function (key) { if ('undefined' === typeof options[key]) { - options[key] = defaults[key]; + options[key] = myDefaults[key]; } }); results._options = options; @@ -67,3 +67,53 @@ Challenge.get = function (defaults, domain, key, done) { Challenge.remove = function (defaults, domain, key, done) { fs.unlink(path.join(defaults.webrootPath, key), done); }; + +Challenge.loopback = function (defaults, domain, key, done) { + var hostname = domain + (defaults.test ? ':' + defaults.test : ''); + 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); + }); + }).on('error', function (err) { + done(err); + }); +}; + +Challenge.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; } + + // test is actually the port to be used + myDefaults.test = args.test; + 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); + }); + }); + }); +}; diff --git a/package.json b/package.json index 6488f6a..8b66ab5 100644 --- a/package.json +++ b/package.json @@ -29,5 +29,9 @@ "homepage": "https://github.com/Daplie/le-challenge-fs#readme", "dependencies": { "mkdirp": "^0.5.1" + }, + "devDependencies": { + "finalhandler": "^0.5.0", + "serve-static": "^1.11.1" } } diff --git a/test.js b/test.js index a8111f2..03a0354 100644 --- a/test.js +++ b/test.js @@ -1,6 +1,8 @@ 'use strict'; -var challenge = require('./').create({ debug: true, webrootPath: '/tmp/acme-challenge' }); +//var httpsOptions = require('localhost.daplie.com-certificates').merge({}); +var webrootPath = '/tmp/acme-challenge'; +var challenge = require('./').create({ debug: true, webrootPath: webrootPath }); var opts = challenge.getOptions(); var domain = 'example.com'; @@ -12,17 +14,13 @@ challenge.remove(opts, domain, token, function () { challenge.set(opts, domain, token, key, function (err) { // if there's an error, there's a problem - if (err) { - throw err; - } + if (err) { throw err; } // throw new Error("manually check /tmp/acme-challenge"); challenge.get(opts, domain, token, function (err, _key) { // if there's an error, there's a problem - if (err) { - throw err; - } + if (err) { throw err; } // should retrieve the key if (key !== _key) { @@ -31,9 +29,7 @@ challenge.remove(opts, domain, token, function () { challenge.remove(opts, domain, token, function () { // if there's an error, there's a problem - if (err) { - throw err; - } + if (err) { throw err; } challenge.get(opts, domain, token, function (err, _key) { // error here is okay @@ -43,9 +39,33 @@ challenge.remove(opts, domain, token, function () { throw new Error("FAIL: should not get key"); } - console.info('PASS'); + console.info('[PASS] unit test'); }); }); }); }); }); + +function loopbackTest() { + var http = require('http'); + var serveStatic = require('serve-static')(webrootPath, { dotfiles: 'allow' }); + var finalhandler = require('finalhandler'); + var server = http.createServer(function (req, res) { + req.url = req.url.replace(/^\/\.well-known\/acme-challenge\//, '/'); + serveStatic(req, res, finalhandler(req, res)); + }); + + server.listen(0, function () { + var port = server.address().port; + + opts.webrootPath = webrootPath; + opts.test = port; + challenge.test(opts, 'localhost', 'foo', 'bar', function (err) { + server.close(); + if (err) { console.error(err.stack); return; } + + console.info('[PASS] localhost loopback'); + }); + }); +} +loopbackTest();