[DynamicXml] parse doc as html if served with text/html content type (#10607)

This commit is contained in:
chris48s
2024-10-12 09:07:28 +01:00
committed by GitHub
parent b85cfc7c1e
commit f3e0cc06f4
3 changed files with 62 additions and 4 deletions

View File

@@ -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 })

View File

@@ -20,6 +20,29 @@ const exampleXml = `<?xml version="1.0"?>
</catalog>
`
const exampleHtml = `<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>Herman Melville - Moby-Dick</h1>
<div>
<p>
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.
</p>
</div>
</body>
</html>
`
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'],
})
})
})

View File

@@ -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',
})