diff --git a/services/dynamic/dynamic-xml.service.js b/services/dynamic/dynamic-xml.service.js index bc24a20a87903..8654863c6d4c4 100644 --- a/services/dynamic/dynamic-xml.service.js +++ b/services/dynamic/dynamic-xml.service.js @@ -70,7 +70,7 @@ export default class DynamicXml extends BaseService { static defaultBadgeData = { label: 'custom badge' } - transform({ pathExpression, buffer }) { + transform({ pathExpression, buffer, contentType = 'text/xml' }) { // e.g. //book[2]/@id const pathIsAttr = ( pathExpression.split('/').slice(-1)[0] || '' @@ -78,14 +78,20 @@ export default class DynamicXml extends BaseService { let parsed try { - parsed = new DOMParser().parseFromString(buffer, 'text/xml') + parsed = new DOMParser().parseFromString(buffer, contentType) } catch (e) { throw new InvalidResponse({ prettyMessage: e.message }) } let values try { - values = xpath.select(pathExpression, parsed) + if (contentType === 'text/html') { + values = xpath + .parse(pathExpression) + .select({ node: parsed, isHtml: true }) + } else { + values = xpath.select(pathExpression, parsed) + } } catch (e) { throw new InvalidParameter({ prettyMessage: e.message }) } @@ -122,16 +128,25 @@ export default class DynamicXml extends BaseService { } async handle(_namedParams, { url, query: pathExpression, prefix, suffix }) { - const { buffer } = await this._request({ + const { buffer, res } = await this._request({ url, options: { headers: { Accept: 'application/xml, text/xml' } }, httpErrors, logErrors: [], }) + let contentType = 'text/xml' + if ( + res.headers['content-type'] && + res.headers['content-type'].includes('text/html') + ) { + contentType = 'text/html' + } + const { values: value } = this.transform({ pathExpression, buffer, + contentType, }) return renderDynamicBadge({ value, prefix, suffix }) diff --git a/services/dynamic/dynamic-xml.spec.js b/services/dynamic/dynamic-xml.spec.js index e239545656db7..64d2509c85881 100644 --- a/services/dynamic/dynamic-xml.spec.js +++ b/services/dynamic/dynamic-xml.spec.js @@ -20,6 +20,29 @@ const exampleXml = ` ` +const exampleHtml = ` + + + + +

Herman Melville - Moby-Dick

+
+

+ Availing himself of the mild, summer-cool weather that now reigned in these + latitudes, and in preparation for the peculiarly active pursuits shortly to + be anticipated, Perth, the begrimed, blistered old blacksmith, had not + removed his portable forge to the hold again, after concluding his + contributory work for Ahab's leg, but still retained it on deck, fast lashed + to ringbolts by the foremast; being now almost incessantly invoked by the + headsmen, and harpooneers, and bowsmen to do some little job for them; + altering, or repairing, or new shaping their various weapons and boat + furniture. +

+
+ + +` + describe('DynamicXml', function () { describe('transform()', function () { beforeEach(function () { @@ -126,5 +149,12 @@ describe('DynamicXml', function () { }).expect({ values: ["XML Developer's Guide", '44.95'], }) + given({ + pathExpression: '//h1[1]', + buffer: exampleHtml, + contentType: 'text/html', + }).expect({ + values: ['Herman Melville - Moby-Dick'], + }) }) }) diff --git a/services/dynamic/dynamic-xml.tester.js b/services/dynamic/dynamic-xml.tester.js index ffaaa2ebb90a7..ac51f4c1b802c 100644 --- a/services/dynamic/dynamic-xml.tester.js +++ b/services/dynamic/dynamic-xml.tester.js @@ -215,3 +215,16 @@ t.create('query with type conversion to number') message: '44.95', color: 'blue', }) + +t.create('query HTML document') + .get( + `.json?${queryString.stringify({ + url: 'https://httpbin.org/html', + query: '//h1[1]', + })}`, + ) + .expectBadge({ + label: 'custom badge', + message: 'Herman Melville - Moby-Dick', + color: 'blue', + })