update error handling

This commit is contained in:
AJ ONeal 2015-12-19 22:25:11 +00:00
parent c92a9f1864
commit aa6119378a
1 changed files with 107 additions and 28 deletions

View File

@ -7,7 +7,6 @@
'use strict'; 'use strict';
module.exports.create = function (deps) { module.exports.create = function (deps) {
var NOOP=function () {}, log=NOOP;
var request=deps.request; var request=deps.request;
var toStandardB64 = deps.leUtils.toStandardB64; var toStandardB64 = deps.leUtils.toStandardB64;
var importPemPrivateKey = deps.leCrypto.importPemPrivateKey; var importPemPrivateKey = deps.leCrypto.importPemPrivateKey;
@ -16,6 +15,8 @@ module.exports.create = function (deps) {
var Acme = deps.Acme; var Acme = deps.Acme;
function getCert(options, cb) { function getCert(options, cb) {
var NOOP = function () {};
var log = options.debug ? console.log : NOOP;
var state={ var state={
validatedDomains:[] validatedDomains:[]
, validAuthorizationUrls:[] , validAuthorizationUrls:[]
@ -56,6 +57,47 @@ module.exports.create = function (deps) {
return handleErr(err, 'Failed to parse privateKey'); return handleErr(err, 'Failed to parse privateKey');
} }
function bodyToError(res, body) {
var err;
if (!body) {
err = new Error("[Error] letiny-core: no request body");
err.code = "E_NO_RESPONSE_BODY";
throw err;
}
if ('{' === body[0] || '{' === String.fromCharCode(body[0])) {
try {
body = JSON.parse(body);
} catch(e) {
err = new Error("[Error] letiny-core: body could not be parsed");
err.code = "E_BODY_PARSE";
err.description = body;
throw err;
}
}
if (Math.floor(res.statusCode / 100) !== 2) {
err = new Error("[Error] letiny-core: not 200 ok");
err.code = "E_STATUS_CODE";
err.type = body.type
err.description = body;
err.detail = body.detail;
throw err;
}
if (body.type && body.detail) {
err = new Error("[Error] letiny-core: " + body.detail);
err.code = body.type;
err.type = body.type;
err.description = body.detail;
err.detail = body.detail;
throw err;
}
return body;
}
nextDomain(); nextDomain();
function nextDomain() { function nextDomain() {
@ -98,7 +140,7 @@ module.exports.create = function (deps) {
state.authorizationUrl=res.headers.location; state.authorizationUrl=res.headers.location;
state.newCertUrl=links.next; state.newCertUrl=links.next;
authz=JSON.parse(body); authz=body;
httpChallenges=authz.challenges.filter(function(x) { httpChallenges=authz.challenges.filter(function(x) {
return x.type==='http-01'; return x.type==='http-01';
@ -136,11 +178,22 @@ module.exports.create = function (deps) {
return handleErr(err, 'Authorization status request failed ('+res.statusCode+')'); return handleErr(err, 'Authorization status request failed ('+res.statusCode+')');
} }
authz=JSON.parse(body); authz=body;
if (authz.status==='pending') { if (authz.status==='pending') {
setTimeout(function() { setTimeout(function() {
request.get(state.authorizationUrl, {}, function(err, res, body) { request({
method: 'GET'
, url: state.authorizationUrl
}, function(err, res, body) {
if (!err && res.body) {
try {
body = bodyToError(res, body);
} catch(e) {
err = e;
}
}
ensureValidation(err, res, body, unlink); ensureValidation(err, res, body, unlink);
}); });
}, 1000); }, 1000);
@ -172,12 +225,17 @@ module.exports.create = function (deps) {
function downloadCertificate(err, res, body) { function downloadCertificate(err, res, body) {
var links, certUrl; var links, certUrl;
if (err || Math.floor(res.statusCode/100)!==2) { if (err) {
log('Certificate request failed with error ', err); handleErr(err, 'Certificate request failed');
if (body) { return;
log(body.toString());
} }
return handleErr(err, 'Certificate request failed');
if (Math.floor(res.statusCode/100)!==2) {
err = new Error("invalid status code: " + res.statusCode);
err.code = "E_STATUS_CODE";
err.description = body;
handleErr(err);
return;
} }
links=Acme.parseLink(res.headers.link); links=Acme.parseLink(res.headers.link);
@ -189,33 +247,54 @@ module.exports.create = function (deps) {
state.certificate=body; state.certificate=body;
certUrl=res.headers.location; certUrl=res.headers.location;
request.get({ request({
url:certUrl, method: 'GET'
encoding:null , url: certUrl
, encoding: null
}, function(err, res, body) { }, function(err, res, body) {
if (!err) {
try {
body = bodyToError(res, body);
} catch(e) {
err = e;
}
}
if (err) { if (err) {
return handleErr(err, 'Failed to fetch cert from '+certUrl); return handleErr(err, 'Failed to fetch cert from '+certUrl);
} }
if (res.statusCode!==200) { if (res.statusCode!==200) {
return handleErr(err, 'Failed to fetch cert from '+certUrl, res.body.toString()); return handleErr(err, 'Failed to fetch cert from '+certUrl, res.body.toString());
} }
if (body.toString()!==state.certificate.toString()) { if (body.toString()!==state.certificate.toString()) {
handleErr(null, 'Cert at '+certUrl+' did not match returned cert'); return handleErr(null, 'Cert at '+certUrl+' did not match returned cert');
} else { }
log('Successfully verified cert at '+certUrl); log('Successfully verified cert at '+certUrl);
log('Requesting issuer certificate...'); log('Requesting issuer certificate...');
request.get({ request({
url:links.up, method: 'GET'
encoding:null , url: links.up
, encoding: null
}, function(err, res, body) { }, function(err, res, body) {
if (!err) {
try {
body = bodyToError(res, body);
} catch(e) {
err = e;
}
}
if (err || res.statusCode!==200) { if (err || res.statusCode!==200) {
return handleErr(err, 'Failed to fetch issuer certificate'); return handleErr(err, 'Failed to fetch issuer certificate');
} }
state.caCert=certBufferToPem(body); state.caCert=certBufferToPem(body);
log('Requesting issuer certificate: done'); log('Requesting issuer certificate: done');
done(); done();
}); });
}
}); });
} }