UNPKG

recurly-js

Version:

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

153 lines (141 loc) 4.76 kB
'use strict'; var https = require('https'); var pjson = require('../package.json'); var Xml2js = require('xml2js'); exports.create = function (config) { config.RECURLY_HOST = config.SUBDOMAIN + '.recurly.com'; var parser = new Xml2js.Parser(config.XML2JS_OPTIONS || { explicitArray: false }); return { request: function (route, callback, data) { var endpoint = route[0]; var method = route[1]; var headers = route[2]; var that = this; var options = { host: config.RECURLY_HOST, port: 443, path: endpoint, method: method, 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': 'umayr/recurly-node/' + 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); } } }; };