UNPKG

mozu-node-sdk

Version:

Mozu JavaScript SDK for Node.js and Arc.js environments

136 lines (127 loc) 5.15 kB
/* eslint-disable complexity */ 'use strict'; var constants = require('../constants'); var extend = require('./tiny-extend'); var url = require('url'); var protocolHandlers = { 'http:': require('http'), 'https:': require('https') }; var streamToCallback = require('./stream-to-callback'); var parseJsonDates = require('./parse-json-dates'); var errorify = require('./errorify'); var zlib = require('zlib'); var ACCEPT_ENCODING = ''; if (zlib.createBrotliDecompress && zlib.createGunzip) { ACCEPT_ENCODING = 'br;q=1.0, gzip;q=0.8'; } else if (zlib.createGunzip) { ACCEPT_ENCODING = 'gzip;q=1.0'; } var USER_AGENT = 'Mozu Node SDK v' + constants.version + ' (Node.js ' + process.version + '; ' + process.platform + ' ' + process.arch + ')'; /** * Handle headers */ function makeHeaders(conf, payload) { var headers; function iterateHeaders(memo, key) { if (conf.context[constants.headers[key]]) { if (key === 'JWT') { memo[constants.jwtHeader] = conf.context[constants.headers[key]].indexOf(constants.jwtHeaderValuePrefix) === -1 ? constants.jwtHeaderValuePrefix + conf.context[constants.headers[key]] : conf.context[constants.headers[key]]; } else { memo[constants.headerPrefix + constants.headers[key]] = conf.context[constants.headers[key]]; } } return memo; } if (conf.scope && conf.scope & constants.scopes.NONE) { headers = {}; } else if (conf.scope && conf.scope & constants.scopes.APP_ONLY) { headers = ['APPCLAIMS'].reduce(iterateHeaders, {}); } else { headers = Object.keys(constants.headers).reduce(iterateHeaders, {}); } if (payload) { headers['Content-Length'] = payload.length.toString(); } if (headers['Authorization'] && headers['x-vol-user-claims']) delete headers['x-vol-user-claims']; if (headers['Authorization'] && headers['x-vol-app-claims']) delete headers['x-vol-app-claims']; return extend({ 'Accept': 'application/json', 'Accept-Encoding': ACCEPT_ENCODING, 'Connection': 'close', 'Content-Type': 'application/json; charset=utf-8', 'User-Agent': USER_AGENT }, headers, conf.headers || {}); } /** * Make an HTTP request to the Mozu API. This method populates headers based on the scope of the supplied context. * @param {Object} options The request options, to be passed to the `request` module. Look up on NPM for details. * @return {Promise<ApiResponse,ApiError>} A Promise that will fulfill as the JSON response from the API, or reject with an error as JSON from the API. */ module.exports = function (options, transform) { var conf = extend({}, options); conf.method = (conf.method || 'get').toUpperCase(); var payload; if (conf.body) { payload = conf.body; if (typeof payload !== "string" && !Buffer.isBuffer(payload)) { payload = JSON.stringify(payload); } if (typeof payload === "string") { payload = new Buffer(payload); } } conf.headers = makeHeaders(conf, payload); var uri = url.parse(conf.url); var protocolHandler = protocolHandlers[uri.protocol]; if (!protocolHandler) { throw new Error('Protocol ' + uri.protocol + ' not supported.'); } return new Promise(function (resolve, reject) { options = extend({}, options); delete options.headers; var requestOptions = extend({ hostname: uri.hostname, port: uri.port || (uri.protocol === 'https:' ? 443 : 80), method: conf.method, path: uri.path, headers: conf.headers, agent: conf.agent }, options); if (typeof transform === "function") { requestOptions = transform(requestOptions); } var complete = false; var request = protocolHandler.request(requestOptions, function (response) { streamToCallback(response, function (err, body) { complete = true; if (err) return reject(errorify(err, extend({ statusCode: response.statusCode, url: response.req.path }, response.headers))); if (body) { try { if (response.headers["content-type"] && (response.headers["content-type"].indexOf('json') > -1 || response.headers["content-type"].indexOf('text/plain') > -1)) { body = JSON.parse(body, conf.parseDates !== false && parseJsonDates); } } catch (e) { return reject(new Error('Response was not valid JSON: ' + e.message + '\n\n-----\n' + body)); } } if (response && response.statusCode >= 400 && response.statusCode < 600) { return reject(errorify(body || response, extend({ statusCode: response.statusCode, url: response.req ? response.req.path : "" }, response.headers))); } return resolve(body); }); }); var timeout = options.timeout || 20000; request.setTimeout(timeout, function () { if (!complete) { request.abort(); reject(errorify("Timeout occurred: request to " + conf.url + " took more than " + timeout / 1000 + " seconds to complete.")); } }); request.on('error', function (err) { reject(errorify(err, request)); }); if (payload) request.write(payload); request.end(); }); };