184 lines
4.0 KiB
JavaScript
184 lines
4.0 KiB
JavaScript
|
|
'use strict';
|
||
|
|
|
||
|
|
var url = require("url")
|
||
|
|
, util = require("util")
|
||
|
|
, Q = require("q")
|
||
|
|
, axios = require("axios")
|
||
|
|
, httpAdapter = require("axios/lib/adapters/http")
|
||
|
|
, errors = require("./errors.js")
|
||
|
|
, debug = /hue-api/.test(process.env.NODE_DEBUG)
|
||
|
|
;
|
||
|
|
|
||
|
|
var defaultOptions = {
|
||
|
|
adapter: httpAdapter,
|
||
|
|
};
|
||
|
|
|
||
|
|
function buildOptions(command, parameters) {
|
||
|
|
var options = {
|
||
|
|
adapter: httpAdapter,
|
||
|
|
debug: debug,
|
||
|
|
headers: {}
|
||
|
|
},
|
||
|
|
body,
|
||
|
|
urlObj = {
|
||
|
|
protocol: parameters.ssl ? "https" : "http",
|
||
|
|
hostname: parameters.host
|
||
|
|
};
|
||
|
|
|
||
|
|
if (parameters.port) {
|
||
|
|
urlObj.port = parameters.port;
|
||
|
|
}
|
||
|
|
|
||
|
|
options.timeout = parameters.timeout || 10000;
|
||
|
|
options.method = command.method || "GET";
|
||
|
|
|
||
|
|
if (command.getPath) {
|
||
|
|
urlObj.pathname = command.getPath(parameters);
|
||
|
|
} else {
|
||
|
|
throw new errors.ApiError("Cannot get the path to invoke from the command");
|
||
|
|
}
|
||
|
|
options.url = url.format(urlObj);
|
||
|
|
|
||
|
|
// Check if the command has body arguments and process them accordingly
|
||
|
|
if (command.bodyArguments && command.buildRequestBody) {
|
||
|
|
body = command.buildRequestBody(parameters.values);
|
||
|
|
|
||
|
|
if (command.bodyType === "application/json") {
|
||
|
|
options.responseType = "json";
|
||
|
|
options.data = JSON.stringify(body);
|
||
|
|
} else {
|
||
|
|
throw new errors.ApiError("No support for " + command.bodyType + " in requests.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (command.response) {
|
||
|
|
options.headers.Accept = command.response;
|
||
|
|
}
|
||
|
|
|
||
|
|
return options;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getError(jsonObject) {
|
||
|
|
var result = null
|
||
|
|
, idx = 0
|
||
|
|
, len = 0
|
||
|
|
;
|
||
|
|
|
||
|
|
if (jsonObject) {
|
||
|
|
if (util.isArray(jsonObject)) {
|
||
|
|
for (idx = 0, len = jsonObject.length; idx < len; idx++) {
|
||
|
|
result = getError(jsonObject[idx]);
|
||
|
|
// Stop on the first error
|
||
|
|
if (result) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (jsonObject.error) {
|
||
|
|
return {
|
||
|
|
type: jsonObject.error.type,
|
||
|
|
description: jsonObject.error.description,
|
||
|
|
address: jsonObject.error.address
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function checkForError(result) {
|
||
|
|
var jsonResult
|
||
|
|
, jsonError
|
||
|
|
;
|
||
|
|
|
||
|
|
jsonResult = result.data;
|
||
|
|
jsonError = getError(jsonResult);
|
||
|
|
|
||
|
|
if (jsonError) {
|
||
|
|
throw new errors.ApiError(jsonError);
|
||
|
|
}
|
||
|
|
return jsonResult;
|
||
|
|
}
|
||
|
|
|
||
|
|
function requireStatusCode200(result) {
|
||
|
|
if (result.status !== 200) {
|
||
|
|
throw new errors.ApiError(
|
||
|
|
{
|
||
|
|
type: "Response Error",
|
||
|
|
description: "Unexpected response status; " + result.statusCode,
|
||
|
|
statusCode: result.statusCode
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function generateErrorsIfMatched(map) {
|
||
|
|
return function (result) {
|
||
|
|
if (map && map[result.statusCode]) {
|
||
|
|
throw new errors.ApiError({
|
||
|
|
type: result.statusCode,
|
||
|
|
message: map[result.statusCode]
|
||
|
|
});
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports.invoke = function (command, parameters) {
|
||
|
|
var options = buildOptions(command, parameters)
|
||
|
|
, promise
|
||
|
|
;
|
||
|
|
|
||
|
|
//promise = requestUtil.request(options);
|
||
|
|
promise = wrapAxios(axios(options));
|
||
|
|
|
||
|
|
if (command.statusCodeMap) {
|
||
|
|
promise = promise.then(generateErrorsIfMatched(command.statusCodeMap));
|
||
|
|
}
|
||
|
|
|
||
|
|
promise = promise
|
||
|
|
.then(requireStatusCode200)
|
||
|
|
.then(function (requestResult) {
|
||
|
|
var result;
|
||
|
|
|
||
|
|
if (options.headers.Accept === "application/json") {
|
||
|
|
result = checkForError(requestResult);
|
||
|
|
} else {
|
||
|
|
result = requestResult.data;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
});
|
||
|
|
|
||
|
|
if (command.postProcessing) {
|
||
|
|
command.postProcessing.forEach(function (fn) {
|
||
|
|
promise = promise.then(fn);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return promise;
|
||
|
|
};
|
||
|
|
|
||
|
|
module.exports.simpleGet = function (uri) {
|
||
|
|
return wrapAxios(axios.get(uri, defaultOptions))
|
||
|
|
.then(requireStatusCode200)
|
||
|
|
.then(function(result) {
|
||
|
|
return result.data;
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Wrap an axios ES6 promise inside a Q promise.
|
||
|
|
* @param promise The axios promise to wrap
|
||
|
|
* @returns {*|promise}
|
||
|
|
*/
|
||
|
|
function wrapAxios(promise) {
|
||
|
|
var deferred = Q.defer();
|
||
|
|
|
||
|
|
promise.then(function (result) {
|
||
|
|
deferred.resolve(result);
|
||
|
|
})
|
||
|
|
.catch(function (err) {
|
||
|
|
deferred.reject(err);
|
||
|
|
});
|
||
|
|
|
||
|
|
return deferred.promise;
|
||
|
|
}
|