UNPKG

recurly-nodejs

Version:

Library for accessing the api for the Recurly recurring billing service.

152 lines (142 loc) 4.26 kB
'use strict'; var https = require('https'); var pjson = require('../package.json'); var Xml2js = require('xml2js'); exports.create = function(config) { var host = config.SUBDOMAIN ? `${config.SUBDOMAIN}.${config.HOST}` : config.HOST; var port = config.PORT || 443; var rejectUnauthorized = typeof config.REJECT_UNAUTHORIZED === 'boolean' ? config.REJECT_UNAUTHORIZED : true; var parser = new Xml2js.Parser(config.XML2JS_OPTIONS || { explicitArray: false }); return { request: function(route, callback, data) { var path = route[0]; var method = route[1]; var headers = route[2]; var that = this; var options = { host, port, method, path, rejectUnauthorized, headers: { Authorization: 'Basic ' + new Buffer(config.API_KEY).toString('base64'), Accept: 'application/xml', 'Content-Length': data ? Buffer.byteLength(data, 'utf8') : 0, 'Content-Type': 'application/xml; charset=utf-8', 'User-Agent': 'recurly-nodejs/' + pjson.version, }, }; if (config.API_VERSION) { options.headers['X-Api-Version'] = config.API_VERSION; } if (headers) { for (var p in headers) { if (!headers.hasOwnProperty(p)) continue; options.headers[p] = headers[p]; } } if (method.toLowerCase() === 'post' || method.toLowerCase() === 'put') { options.headers['Content-Type'] = 'application/xml'; that.debug(data); } that.debug(options); var req = https.request(options, function(res) { var responsedata = []; res.on('data', function(d) { responsedata.push(d); }); res.on('end', function() { responsedata = Buffer.concat(responsedata); that.debug('Response is: ' + res.statusCode); that.debug(responsedata); try { // 200–299 success if (res.statusCode >= 200 && res.statusCode <= 299) { if (responsedata === '') { return _cb(res); } else if (options.headers.Accept !== 'application/xml') { return _cb(res, null, responsedata); } return parser.parseString(responsedata, function(err, result) { return _cb(res, null, result); }); } // 400–499 client request errors // 500–599 server errors if ([404, 412, 422, 500].indexOf(res.statusCode) !== -1) { return parser.parseString(responsedata, function(err, result) { return _cb(res, result); }); } if (res.statusCode >= 400) { return parser.parseString(responsedata, function(err, result) { return _cb(res, result); }); } } catch (e) { return _cb(null, e); } }); }); if (data) { req.write(data); } req.end(); req.on('error', function(e) { return _cb(null, e); }); // fallback for backward compatibility function _cb(res, err, data) { // callback objects acquired from parent scope if (typeof callback === 'undefined') { throw new Error('Missing argument: callback function'); } if (typeof callback !== 'function') { throw new Error('Callback should be a function'); } if (callback.length === 2) { if (err) { return callback(_wrapResponse(res, err)); } return callback(null, _wrapResponse(res, data)); } // backward compatibility for not node.js style callbacks // TBD: skip in next version? else if (callback.length === 1) { var toreturn = { status: 'ok', data: '', headers: res ? res.headers : null }; if (err) { toreturn.status = 'error'; if (!res || err === Error || err instanceof Error) { toreturn.description = err; } else if (res.statusCode >= 400) { toreturn.data = res.statusCode; toreturn.additional = err; } else { toreturn.data = err; } return callback(toreturn); } toreturn.data = data; toreturn.description = res.statusCode; return callback(toreturn); } } function _wrapResponse(res, data) { if (!res) { return { data: data && data.stack ? data.stack : data }; } return { statusCode: res.statusCode, headers: res.headers, data: data, }; } }, debug: function(s) { if (config.DEBUG) { console.log(s); } }, }; };