Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 })
Comment on lines +88 to +91
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required so that we don't have to explicitly use a namespace on every selector for HTML documents

See

for more detail

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