Skip to content

Commit

Permalink
[DynamicXml] parse doc as html if served with text/html content type (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
chris48s authored Oct 12, 2024
1 parent b85cfc7 commit f3e0cc0
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 4 deletions.
23 changes: 19 additions & 4 deletions services/dynamic/dynamic-xml.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,28 @@ 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] || ''
).startsWith('@')

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 })
}
Expand Down Expand Up @@ -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 })
Expand Down
30 changes: 30 additions & 0 deletions services/dynamic/dynamic-xml.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {
Expand Down Expand Up @@ -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'],
})
})
})
13 changes: 13 additions & 0 deletions services/dynamic/dynamic-xml.tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
})

0 comments on commit f3e0cc0

Please sign in to comment.