UNPKG

opennms

Version:

Client API for the OpenNMS network monitoring platform

257 lines (217 loc) 7.72 kB
import axios from 'axios'; import {AxiosStatic, AxiosInstance, AxiosResponse, AxiosRequestConfig} from 'axios'; import * as qs from 'qs'; import * as clonedeep from 'lodash.clonedeep'; /** @hidden */ // tslint:disable-next-line const URI = require('urijs'); import {AbstractHTTP} from './AbstractHTTP'; import {OnmsError} from '../api/OnmsError'; import {OnmsHTTPOptions} from '../api/OnmsHTTPOptions'; import {OnmsResult} from '../api/OnmsResult'; import {OnmsServer} from '../api/OnmsServer'; import {log, catRest} from '../api/Log'; import {Category} from 'typescript-logging'; import {Util} from '../internal/Util'; /** @hidden */ const catAxios = new Category('axios', catRest); /** * Implementation of the [[IOnmsHTTP]] interface using Axios: https://github.com/mzabriskie/axios * @module AxiosHTTP * @implements IOnmsHTTP */ export class AxiosHTTP extends AbstractHTTP { /** * The Axios implementation class we'll use for making ReST calls. This is necessary * to make sure we end up with the correct backend (XMLHttpRequest or Node.js 'http') * at runtime. * @hidden */ private axiosImpl: AxiosStatic; /** * The Axios instance we'll use for making ReST calls. This will be reinitialized whenever * the server configuration changes. */ private axiosObj: AxiosInstance; /** * Construct an AxiosHTTP instance. * @param server - The server to connect to. * @param axiosImpl - The Axios implementation class to use. * @param timeout - The default timeout for ReST connections. */ constructor(server?: OnmsServer, axiosImpl?: AxiosStatic, timeout = 10000) { super(server, timeout); this.axiosImpl = axiosImpl || axios; } /** * Make an HTTP GET call using `axios.request({method:'get'})`. */ public get(url: string, options?: OnmsHTTPOptions) { const realUrl = this.getServer(options).resolveURL(url); const opts = this.getConfig(options); const urlObj = new URI(realUrl); urlObj.search(opts.params); log.debug('GET ' + urlObj.toString(), catAxios); opts.method = 'get'; opts.url = realUrl; return this.getImpl(options).request(opts).then((response) => { let type; if (response.headers && response.headers['content-type']) { type = response.headers['content-type']; } return OnmsResult.ok(this.getData(response), undefined, response.status, type); }).catch((err) => { throw this.handleError(err, opts); }); } /** * Make an HTTP PUT call using `axios.request({method:'put'})`. */ public put(url: string, options?: OnmsHTTPOptions) { const realUrl = this.getServer(options).resolveURL(url); const opts = this.getConfig(options); const urlObj = new URI(realUrl); urlObj.search(opts.params); log.debug('PUT ' + urlObj.toString(), catAxios); opts.data = Object.apply({}, opts.params); opts.method = 'put'; opts.url = realUrl; return this.getImpl(options).request(opts).then((response) => { let type; if (response.headers && response.headers['content-type']) { type = response.headers['content-type']; } return OnmsResult.ok(this.getData(response), undefined, response.status, type); }).catch((err) => { throw this.handleError(err, opts); }); } /** * Make an HTTP POST call using `axios.request({method:'post'})`. */ public post(url: string, options?: OnmsHTTPOptions) { const realUrl = this.getServer(options).resolveURL(url); const opts = this.getConfig(options); const urlObj = new URI(realUrl); urlObj.search(opts.params); log.debug('POST ' + urlObj.toString(), catAxios); opts.method = 'post'; opts.url = realUrl; return this.getImpl(options).request(opts).then((response) => { let type; if (response.headers && response.headers['content-type']) { type = response.headers['content-type']; } return OnmsResult.ok(this.getData(response), undefined, response.status, type); }).catch((err) => { throw this.handleError(err, opts); }); } /** * Make an HTTP DELETE call using `axios.request({method:'delete'})`. */ public httpDelete(url: string, options?: OnmsHTTPOptions) { const realUrl = this.getServer(options).resolveURL(url); const opts = this.getConfig(options); const urlObj = new URI(realUrl); urlObj.search(opts.params); log.debug('DELETE ' + urlObj.toString(), catAxios); opts.method = 'delete'; opts.url = realUrl; return this.getImpl(options).request(opts).then((response) => { let type; if (response.headers && response.headers['content-type']) { type = response.headers['content-type']; } return OnmsResult.ok(this.getData(response), undefined, response.status, type); }).catch((err) => { throw this.handleError(err, opts); }); } /** * Clear the current [[AxiosInstance]] so it is recreated on next request with the * new server configuration. */ protected onSetServer() { super.onSetServer(); this.axiosObj = undefined; } /** * Internal method to turn [[OnmsHTTPOptions]] into an [[AxiosRequestConfig]] object. * @hidden */ private getConfig(options?: OnmsHTTPOptions): AxiosRequestConfig { const allOptions = this.getOptions(options); const ret = { transformResponse: [], // we do this so we can post-process only on success } as AxiosRequestConfig; if (allOptions.auth && allOptions.auth.username && allOptions.auth.password) { ret.auth = { password: allOptions.auth.password, username: allOptions.auth.username, }; } if (allOptions.timeout) { ret.timeout = allOptions.timeout; } if (allOptions.headers) { ret.headers = clonedeep(allOptions.headers); } else { ret.headers = {}; } if (!ret.headers.accept) { ret.headers.accept = 'application/json'; } if (!ret.headers['content-type']) { ret.headers['content-type'] = 'application/json;charset=utf-8'; } const type = ret.headers.accept; ret.transformResponse = []; if (type === 'application/json') { ret.responseType = 'json'; } else if (type === 'text/plain') { ret.responseType = 'text'; } else if (type === 'application/xml') { ret.responseType = 'text'; } else { throw new OnmsError('Unhandled "Accept" header: ' + type); } if (allOptions.parameters) { ret.params = clonedeep(allOptions.parameters); } if (allOptions.data) { ret.data = clonedeep(allOptions.data); } return ret; } /** * Internal method for getting/constructing an Axios object on-demand, * based on the current server configuration. * @hidden */ private getImpl(options?: OnmsHTTPOptions) { if (!this.axiosObj) { const server = this.getServer(options); if (!server) { throw new OnmsError('You must set a server before attempting to make queries using Axios!'); } const allOptions = this.getOptions(options); const axiosOpts = { auth: { password: allOptions.auth.password, username: allOptions.auth.username, }, baseURL: server.url, timeout: allOptions.timeout, withCredentials: true, } as AxiosRequestConfig; if (typeof XMLHttpRequest !== 'undefined') { axiosOpts.adapter = require('axios/lib/adapters/xhr.js'); } else if (typeof process !== 'undefined') { axiosOpts.adapter = require('axios/lib/adapters/http.js'); } this.axiosObj = this.axiosImpl.create(axiosOpts); } return this.axiosObj; } }