message-hub-rest
Version:
Node.js module for connecting to the Kafka REST interface of IBM Message Hub.
213 lines (188 loc) • 6.62 kB
JavaScript
/**
* Copyright 2015, 2018 IBM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Licensed Materials - Property of IBM
* © Copyright IBM Corp. 2015, 2018
*/
;
var Url = require('url');
var Utils = require('./utils');
var Q = require('q');
var CONTENT_TYPE = 'application/vnd.kafka.binary.v1+json';
var APPLICATION_JSON = 'application/json';
/**
* Client (Constructor)
* Constructs a new Client object, provided with Bluemix VCAP_SERVICES
* and additional options used to help connect to a particular service.
* @param services Object retrieved from process.env.VCAP_SERVICES or cfenv package.
* @param opts Additional options used to connect to a particular service.
* Current keys:
* - isStaging (Boolean): If set to true, the constructor will look for the
* "messagehubstaging" key, rather than "messagehub".
*/
var Client = function(services, opts) {
opts = opts || {
'https': true,
};
if(!opts.hasOwnProperty('https')) {
opts.https = true;
}
this.config = opts;
this.topics.parent = this;
if(services !== undefined) {
var serviceNamePrefix = "messagehub";
var serviceIndex = 0;
var serviceName;
// Search for 'messagehub' prefix.
for(var name in services) {
if(name.substr(0, serviceNamePrefix.length) === serviceNamePrefix) {
serviceName = name;
}
}
if(services[serviceName]) {
for(var index in services[serviceName]) {
if(services[serviceName][index].hasOwnProperty("label")
&& services[serviceName][index].label == serviceName)
{
serviceIndex = index;
}
}
this.apiKey = services[serviceName][serviceIndex].credentials.api_key;
this.url = Url.parse(services[serviceName][serviceIndex].credentials.kafka_admin_url);
this.consumerInstances = { };
} else {
throw new Error(serviceNamePrefix + '* is not provided in the services environment variable. ' +
'Make sure you have bound the Message Hub service to your Bluemix application');
}
} else {
throw new Error('Provided services environment variable is undefined!');
}
};
Client.prototype.topics = { };
/**
* Client.prototype.topics.get
* Retrieves a list of all topics connected to the provided API key.
*
* @returns Promise object which will be fulfilled when the request
* to the service resolves.
*/
Client.prototype.topics.get = function() {
var requestOptions = {
host: this.parent.url.hostname,
port: this.parent.url.port,
path: '/admin/topics',
method: 'GET',
headers: {
'X-Auth-Token': this.parent.apiKey
},
};
return Utils.request(requestOptions, { https: this.parent.config.https });
};
/**
* Client.prototype.topics.create
* Creates a topic of the specified name.
*
* @param topic The topic name for the service to create.
* @param partitions The number of partitions the topic should use.
* @param retentionHours The number of hours to retain messages on this topic. Minimum is
* 24 hours, if retentionHours is less than this, it will be set to
* the minimum.
* @returns Promise object which will be fulfilled when the request
* to the service resolves.
*/
Client.prototype.topics.create = function(topic, partitions, retentionHours) {
if(topic && typeof(topic) === 'string' && topic.length > 0) {
if(!partitions || (partitions && typeof(partitions) !== 'number') || partitions < 1) {
partitions = 1;
}
if(!retentionHours || (retentionHours && typeof(retentionHours) !== 'number') || retentionHours < 24) {
retentionHours = 24;
}
var requestOptions = {
host: this.parent.url.hostname,
port: this.parent.url.port,
path: '/admin/topics',
method: 'POST',
headers: {
'X-Auth-Token': this.parent.apiKey,
'Content-Type': APPLICATION_JSON
},
};
var retentionMs = retentionHours * 60 * 60 * 1000;
return Utils.request(
requestOptions,
{
https: this.parent.config.https,
acceptedResponseCodes: [202],
ignoredErrorCodes: [42201]
},
{
name: topic,
partitions: partitions,
configs: {
retentionMs: retentionMs
}
});
} else {
var deferred = Q.defer();
if(!topic) {
deferred.reject(new ReferenceError('Provided topic parameter cannot be undefined.'));
} else if(typeof(topic) !== 'string') {
deferred.reject(new TypeError('Provided topic parameter must be of type "string".'));
} else {
deferred.reject(new Error('Provided topic parameter must have length greater than zero.'));
}
return deferred.promise;
}
};
/**
* Client.prototype.topics.delete
* Deletes a topic of the specified name.
*
* @param topic The topic name to delete from the service.
* @returns Promise object which will be fulfilled when the request
* to the service resolves.
*/
Client.prototype.topics.delete = function(topic) {
if(topic && typeof(topic) === 'string' && topic.length > 0) {
var requestOptions = {
host: this.parent.url.hostname,
port: this.parent.url.port,
path: '/admin/topics/' + topic,
method: 'DELETE',
headers: {
'X-Auth-Token': this.parent.apiKey
},
};
return Utils.request(
requestOptions,
{
https: this.parent.config.https,
acceptedResponseCodes: [202]
});
} else {
var deferred = Q.defer();
if(!topic) {
deferred.reject(new ReferenceError('Provided topic parameter cannot be undefined.'));
} else if(typeof(topic) !== 'string') {
deferred.reject(new TypeError('Provided topic parameter must be of type "string".'));
} else {
deferred.reject(new Error('Provided topic parameter must have length greater than zero.'));
}
return deferred.promise;
}
};
module.exports = Client;