diff --git a/lib/harAnalyzer.js b/lib/harAnalyzer.js index b197552..0ee165e 100644 --- a/lib/harAnalyzer.js +++ b/lib/harAnalyzer.js @@ -29,6 +29,47 @@ export class HarAnalyzer { this.dependencies = this.package.dependencies; this.version = this.package.version; } + getFirstPageEntries(url, harData) { + if ('log' in harData) { + harData = harData['log']; + } + + const entries = harData.entries; + if (!Array.isArray(entries)) { + return []; + } + + // A HAR can contain more than one page, for example when a concurrent + // browsertime run ends up in the same browser session (crossed DevTools + // port) and navigates to another website mid-recording. Requests made + // by other pages must not be attributed to the tested website, and if + // the recording doesn't even start with the tested website nothing in + // it can be trusted. + if (url && entries.length > 0) { + const firstUrl = entries[0].request && entries[0].request.url; + if (firstUrl) { + try { + if (new URL(firstUrl).hostname !== new URL(url).hostname) { + return []; + } + } catch { + // Unparsable URLs are handled by the entry loops as before + } + } + } + + const pages = harData.pages; + if (!Array.isArray(pages) || pages.length === 0) { + return entries; + } + const firstPageId = pages[0].id; + if (firstPageId === undefined) { + return entries; + } + return entries.filter(entry => + entry.pageref === undefined || entry.pageref === firstPageId); + } + transform2SimplifiedData(harData, url) { const data = { 'url': url, @@ -41,13 +82,9 @@ export class HarAnalyzer { 'script-files': [] }; - if ('log' in harData) { - harData = harData['log']; - } - let reqIndex = 1; - for (const entry of harData.entries) { + for (const entry of this.getFirstPageEntries(url, harData)) { const req = entry.request; const res = entry.response; const reqUrl = req.url;