/**
* Copyright 2014 IBM Corp. All Rights Reserved.
*
* 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.
*/
"use strict";
var extend = require('extend');
var vcapServices = require('vcap_services');
var helper = require('./helper');
var request = require('request');
/**
* Internal base class that other services inherit from
* @param {Object} options
* @param {String} [options.username] - required unless use_unauthenticated is set
* @param {String} [options.password] - required unless use_unauthenticated is set
* @param {Boolean} [options.use_unauthenticated] - skip credential requirement
* @param {Object} [options.headers]
* @param {Boolean} [options.headers.X-Watson-Learning-Opt-Out=false] - opt-out of data collection
* @param {String} [options.url] - override default service base url
* @private
* @abstract
* @constructor
*/
function BaseService(user_options) {
if (!(this instanceof BaseService)) {
// it might be better to just create a new instance and return that.. but that can't be done here, it has to be done in each individual service. So this is still a good failsafe even in that case.
throw new Error('"new" keyword required to create Watson service instances');
}
var options = extend({}, user_options);
options = this.initCredentials(options);
if (options.url)
{options.url = helper.stripTrailingSlash(options.url);}
this._options = extend({qs: {}, url: this.constructor.URL}, this.serviceDefaults, options);
}
/**
* @private
* @param options
* @returns {*}
*/
BaseService.prototype.initCredentials = function(options) {
if (options.token) {
options.headers = options.headers || {};
options.headers['X-Watson-Authorization-Token'] = options.token;
return options;
}
options.jar = request.jar();
// Get credentials from environment properties or Bluemix
// but prefer credentials provided pragmatically!
options = extend(
{},
this.getCredentialsFromBluemix(this.name),
this.getCredentialsFromEnvironment(this.name),
options
);
if (!options.use_unauthenticated) {
if (!options.username || !options.password) {
throw new Error('Argument error: username and password are required unless use_unauthenticated is set');
}
// Calculate and add Authorization header to base options
var authHeader = {Authorization: 'Basic ' + new Buffer(options.username + ':' + options.password).toString('base64')};
options.headers = extend(authHeader, options.headers);
}
return options;
};
/**
* Pulls credentials from env properties
*
* Property checked is uppercase service.name suffixed by _USERNAME and _PASSWORD
*
* For example, if service.name is speech_to_text, env properties are SPEECH_TO_TEXT_USERNAME and SPEECH_TO_TEXT_PASSWORD
*
* @private
* @param name
* @returns {{username: String|undefined, password: String|undefined}}
*/
BaseService.prototype.getCredentialsFromEnvironment = function(name) {
name = name.toUpperCase();
return {
username: process.env[name + '_USERNAME'],
password: process.env[name + '_PASSWORD'],
url: process.env[name + '_URL']
}
};
/**
* Pulls credentials from VCAP_SERVICES env property that bluemix sets
*
* @private
* @returns {{}}
*/
BaseService.prototype.getCredentialsFromBluemix = function(vcap_services_name) {
return vcapServices.getCredentials(vcap_services_name);
};
/**
* Retrieve this service's credentials - useful for passing to the authorization service
*
* Only returns a URL when token auth is used.
*
* @returns {{username: String, password: String, url: String}}
*/
BaseService.prototype.getCredentials = function() {
return {
username: this._options.username,
password: this._options.password,
url: this._options.url
}
};
module.exports = BaseService;