/**
* @module
*/
'use strict'
// See available emoji at http://emoji.muan.co/
const emojic = require('emojic')
const fastXmlParser = require('fast-xml-parser')
const BaseService = require('./base')
const trace = require('./trace')
const { InvalidResponse } = require('./errors')
/**
* Services which query a XML endpoint should extend BaseXmlService
*
* @abstract
*/
class BaseXmlService extends BaseService {
/**
* Request data from an upstream API serving XML,
* parse it and validate against a schema
*
* @param {object} attrs Refer to individual attrs
* @param {Joi} attrs.schema Joi schema to validate the response against
* @param {string} attrs.url URL to request
* @param {object} [attrs.options={}] Options to pass to request. See
* [documentation](https://github.com/request/request#requestoptions-callback)
* @param {object} [attrs.errorMessages={}] Key-value map of status codes
* and custom error messages e.g: `{ 404: 'package not found' }`.
* This can be used to extend or override the
* [default](https://github.com/badges/shields/blob/master/core/base-service/check-error-response.js#L5)
* @param {object} [attrs.parserOptions={}] Options to pass to fast-xml-parser. See
* [documentation](https://github.com/NaturalIntelligence/fast-xml-parser#xml-to-json)
* @returns {object} Parsed response
* @see https://github.com/request/request#requestoptions-callback
* @see https://github.com/NaturalIntelligence/fast-xml-parser#xml-to-json
*/
async _requestXml({
schema,
url,
options = {},
errorMessages = {},
parserOptions = {},
}) {
const logTrace = (...args) => trace.logTrace('fetch', ...args)
const mergedOptions = {
...{ headers: { Accept: 'application/xml, text/xml' } },
...options,
}
const { buffer } = await this._request({
url,
options: mergedOptions,
errorMessages,
})
const validateResult = fastXmlParser.validate(buffer)
if (validateResult !== true) {
throw new InvalidResponse({
prettyMessage: 'unparseable xml response',
underlyingError: validateResult.err,
})
}
const xml = fastXmlParser.parse(buffer, parserOptions)
logTrace(emojic.dart, 'Response XML (before validation)', xml, {
deep: true,
})
return this.constructor._validate(xml, schema)
}
}
module.exports = BaseXmlService