| 'use strict' |
| |
| const messages = require('./messages') |
| const BaseOperationError = require('./base_operation_error') |
| const rp = require('request-promise') |
| const url = require('url') |
| |
| class Client { |
| constructor (options) { |
| this.options = this.parse_options(options || {}) |
| } |
| |
| parse_options (options) { |
| const api_key = options.api_key || process.env['__OW_API_KEY'] |
| const ignore_certs = options.ignore_certs || false |
| // if apihost is available, parse this into full API url |
| const api = options.api || |
| this.url_from_apihost(options.apihost || process.env['__OW_API_HOST']) |
| |
| if (!api_key) { |
| throw new Error(`${messages.INVALID_OPTIONS_ERROR} Missing api_key parameter.`) |
| } else if (!api) { |
| throw new Error(`${messages.INVALID_OPTIONS_ERROR} Missing either api or apihost parameters.`) |
| } |
| |
| return {api_key, api, ignore_certs, namespace: options.namespace} |
| } |
| |
| url_from_apihost (apihost) { |
| if (!apihost) return apihost |
| let url = `${apihost}/api/v1/` |
| |
| // if apihost does not the protocol, assume HTTPS |
| if (!url.match(/http(s)?:\/\//)) { |
| url = `https://${url}` |
| } |
| |
| return url |
| } |
| |
| request (method, path, options) { |
| const req = this.params(method, path, options) |
| return rp(req).catch(err => this.handle_errors(err)) |
| } |
| |
| params (method, path, options) { |
| return Object.assign({ |
| json: true, |
| method: method, |
| url: this.path_url(path), |
| rejectUnauthorized: !this.options.ignore_certs, |
| headers: { |
| Authorization: this.auth_header() |
| } |
| }, options) |
| } |
| |
| path_url (url_path) { |
| const endpoint = this.api_url() |
| endpoint.pathname = url.resolve(endpoint.pathname, url_path) |
| return url.format(endpoint) |
| } |
| |
| api_url () { |
| return url.parse( |
| this.options.api.endsWith('/') ? this.options.api : this.options.api + '/' |
| ) |
| } |
| |
| auth_header () { |
| const api_key_base64 = Buffer.from(this.options.api_key).toString('base64') |
| return `Basic ${api_key_base64}` |
| } |
| |
| handle_errors (reason) { |
| if (reason.hasOwnProperty('statusCode')) { |
| let error |
| switch (reason.statusCode) { |
| case 400: |
| error = messages.BAD_REQUEST_ERROR |
| break |
| case 401: |
| case 403: |
| error = messages.INVALID_AUTH_ERROR |
| break |
| case 404: |
| error = messages.MISSING_URL_ERROR |
| break |
| case 408: |
| error = messages.INVOKE_TIMEOUT_ERROR |
| break |
| case 409: |
| error = messages.CREATE_CONFLICT_ERROR |
| break |
| case 502: |
| error = messages.ACTION_INVOCATION_ERROR |
| break |
| default: |
| error = messages.API_SYSTEM_ERROR |
| } |
| |
| throw new BaseOperationError(`${error} ${this.err_message(reason.error)}`, reason.error) |
| } |
| |
| throw new Error(`Error encountered calling OpenWhisk: ${reason.message}`) |
| } |
| |
| err_message (error) { |
| if (!error) return 'Missing error message.' |
| |
| if (typeof error.error === 'string') { |
| return error.error |
| } else if (error.response && error.response.result) { |
| const result = error.response.result |
| if (typeof result.error === 'string') { |
| return result.error |
| } else if (typeof result.statusCode === 'number') { |
| return `application error, status code: ${result.statusCode}` |
| } |
| } |
| |
| return 'Missing error message.' |
| } |
| } |
| |
| module.exports = Client |