Source: http-client.js

const axios = require('axios')
const querystring = require('querystring')

const { AUTH_METHODS, ERRORS, MAX_UPLOAD_SIZE } = require('./consts')
const { Util, ValidationError } = require('./util')

/**
 * @typedef {object} HttpClient
 * @property {function} get Method for sending GET requests
 * @property {function} post Method for sending POST requests. Data is transmitted using multipart/form-data
 */

/**
 * Celsius js SDK Http Client
 * @module celsius-js-sdk/http-client
 */

/**
 * Creates and configures HttpClient.
 *
 * @function
 *
 * @param {object} config - contains configuration data
 * @returns {HttpClient}
 */
const HttpClient = function (config) {
  const HttpClient = this
  const util = Util(config)

  HttpClient.config = config
  HttpClient.headers = {
    'X-Cel-Partner-Token': config.partnerKey
  }

  /**
   * Sends HTTP requst to the api.
   *
   * @private
   * @function _dispatchAxiosRequest
   *
   * @param {string} method - Http Method (GET, POST, etc.)
   * @param {string} path - Url that is the target of request
   * @param {object} headers - Headers to be sent with request
   * @param {object} data - Data to be sent with request
   *
   * @returns {Promise} Response
   */

  function _dispatchAxiosRequest (method, path, headers, data) {
    return axios({
      method: method,
      url: config.baseUrl + path,
      headers: headers,
      data: data,
      maxContentLength: MAX_UPLOAD_SIZE
    })
      .then((response) => {
        if (!util.verifyResponse(response.data, response.headers['x-signature'])) {
          return Promise.reject(new Error(ERRORS.RESPONSE_VERIFICATION_FAILED))
        }
        return Promise.resolve(response.data)
      })
      .catch((error) => {
        let err = error
        if (error.response) {
          if (!util.verifyResponse(error.response.data, error.response.headers['x-signature'])) {
            return Promise.reject(new Error(ERRORS.RESPONSE_VERIFICATION_FAILED))
          }

          if (error.response.status >= 400 && error.response.status < 500) {
            return Promise.reject(new ValidationError(error.response))
          }
        }

        return Promise.reject(err)
      })
  }

  /**
   * Adds authentication header to existing headers.
   * Authentication method is read from config.
   * Based on it, appropriate header gets added to existing headers
   * with the value of user secret (also contained in config).
   *
   * @private
   * @function _getHeaders
   *
   * @param {object} config - Contains authentication method and user secret
   * @returns {object} Headers
   */
  function _getHeaders (config) {
    const headers = HttpClient.headers

    if (HttpClient.config.authMethod === AUTH_METHODS.API_KEY) {
      headers['X-Cel-Api-Key'] = config.userSecret
    } else if (HttpClient.config.authMethod === AUTH_METHODS.USER_TOKEN) {
      headers['X-Cel-User-Token'] = config.userSecret
    }

    return headers
  }

  return {
    /**
     * Sends a HTTP GET request.
     *
     * @function get
     *
     * @param {string} path - Endpoint path
     * @param {object} queryParams - Parameters to be sent via query string
     * @param {string} userSecret - User's secret token or api-key
     *
     * @return {object} Response
     */
    get: function (path, queryParams, userSecret) {
      const headers = _getHeaders({ userSecret })
      queryParams = querystring.stringify(queryParams)
      return _dispatchAxiosRequest('GET', path + '?' + queryParams, headers, null)
    },

    /**
     * Sends a HTTP POST request.
     *
     * @function post
     *
     * @param {string} path - Endpoint path
     * @param {object} formFields - Form fields to be sent
     * @param {object} files - Files to be sent
     * @param {string} userSecret - User's secret token or api-key
     *
     * @return {Promise} Response
     */
    post: function (path, formFields, files, userSecret) {
      return new Promise((resolve, reject) => {
        util.getFormData(formFields, files).then((formData) => {
          let headers = _getHeaders({ userSecret })
          headers = formData.getHeaders(headers)

          return resolve(_dispatchAxiosRequest('POST', path, headers, formData))
        })
      })
    }
  }
}

module.exports = {
  HttpClient
}