From 00310d0bd393c13ddd610937c85faa276af1d0c4 Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Wed, 22 Dec 2021 16:22:37 -0800 Subject: [PATCH 1/6] Skip processing fetch for data URLs --- feature/xhr/instrument/index.js | 5 +++++ feature/xhr/instrument/parse-url.js | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/feature/xhr/instrument/index.js b/feature/xhr/instrument/index.js index a783ec778..fe661d833 100644 --- a/feature/xhr/instrument/index.js +++ b/feature/xhr/instrument/index.js @@ -264,6 +264,8 @@ ee.on('fetch-start', function (fetchArguments, dtPayload) { } addUrl(this, url) + if (this.params.protocol === 'data') return + var method = ('' + ((target && target instanceof origRequest && target.method) || opts.method || 'GET')).toUpperCase() this.params.method = method @@ -278,6 +280,9 @@ ee.on('fetch-done', function (err, res) { if (!this.params) { this.params = {} } + + if (this.params.protocol === 'data') return + this.params.status = res ? res.status : 0 // convert rxSize to a number diff --git a/feature/xhr/instrument/parse-url.js b/feature/xhr/instrument/parse-url.js index 99f92e215..ae1b24efd 100644 --- a/feature/xhr/instrument/parse-url.js +++ b/feature/xhr/instrument/parse-url.js @@ -10,6 +10,12 @@ module.exports = function parseUrl (url) { return stringsToParsedUrls[url] } + if (url.indexOf('data:') === 0) { + return { + protocol: 'data' + } + } + var urlEl = document.createElement('a') var location = window.location var ret = {} From 25ca4782d17335858c9b8cf562c2d350441d3c6c Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Mon, 27 Dec 2021 13:02:36 -0800 Subject: [PATCH 2/6] Add tests for new data URL request handling --- feature/xhr/instrument/index.js | 5 ++ tests/browser/xhr/data-url.browser.js | 76 +++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tests/browser/xhr/data-url.browser.js diff --git a/feature/xhr/instrument/index.js b/feature/xhr/instrument/index.js index fe661d833..64921643d 100644 --- a/feature/xhr/instrument/index.js +++ b/feature/xhr/instrument/index.js @@ -264,6 +264,7 @@ ee.on('fetch-start', function (fetchArguments, dtPayload) { } addUrl(this, url) + // Do not generate telemetry for Data URL requests because they don't behave like other network requests if (this.params.protocol === 'data') return var method = ('' + ((target && target instanceof origRequest && target.method) || @@ -281,6 +282,7 @@ ee.on('fetch-done', function (err, res) { this.params = {} } + // Do not generate telemetry for Data URL requests because they don't behave like other network requests if (this.params.protocol === 'data') return this.params.status = res ? res.status : 0 @@ -312,6 +314,9 @@ function end (xhr) { xhr.removeEventListener(handlers[i], this.listener, false) } + // Do not generate telemetry for Data URL requests because they don't behave like other network requests + if (params.protocol && params.protocol === 'data') return + if (params.aborted) return metrics.duration = loader.now() - this.startTime if (!this.loadCaptureCalled && xhr.readyState === 4) { diff --git a/tests/browser/xhr/data-url.browser.js b/tests/browser/xhr/data-url.browser.js new file mode 100644 index 000000000..c14b41c6c --- /dev/null +++ b/tests/browser/xhr/data-url.browser.js @@ -0,0 +1,76 @@ +/* + * Copyright 2020 New Relic Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +const test = require('../../../tools/jil/browser-test') +const ee = require('ee') +const handleEE = ee.get('handle') + +const hasXhr = window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.addEventListener + +require('../../../feature/xhr/instrument') + +test('XHR request for Data URL does not generate telemetry', function(t) { + if (!hasXhr) { + t.pass('xhr is not supported in this browser') + t.end() + return + } + + handleEE.addEventListener('xhr', failCase) + + ee.addEventListener('send-xhr-start', validate) + + var xhr = new XMLHttpRequest() + xhr.open('GET', 'data:,data-uri') + xhr.send() + + function validate (args, xhr) { + t.equals(this.params.protocol, 'data', 'XHR Data URL request recorded') + setTimeout(() => { + handleEE.removeEventListener('xhr', failCase) + ee.removeEventListener('send-xhr-start', validate) + + t.pass('XHR Data URL request did not generate telemetry') + t.end() + }, 100) + } + + function failCase (params, metrics, start) { + t.fail('XHR request for Data URL should not generate telemetry') + handleEE.removeEventListener('xhr', failCase) + } +}) + +test('Data URL Fetch requests do not generate telemetry', function(t) { + if (!window.fetch) { + t.pass('fetch is not supported in this browser') + t.end() + return + } + + handleEE.addEventListener('xhr', failCase) + + ee.addEventListener('fetch-done', validate) + + fetch('data:,dataUrl') + + function validate () { + t.equals(this.params.protocol, 'data', 'Fetch data URL request recorded') + + setTimeout(() => { + handleEE.removeEventListener('xhr', failCase) + ee.removeEventListener('fetch-done', validate) + + t.pass('Fetch data URL request did not generate telemetry') + t.end() + }, 100) + } + + function failCase(params, metrics, start) { + t.fail('Data URL Fetch requests should not generate telemetry') + handleEE.removeEventListener('xhr', failCase) + ee.removeEventListener('fetch-done', validate) + } +}) From d720dccab07920cc10c1d75c3660190caca82898 Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Mon, 27 Dec 2021 13:03:39 -0800 Subject: [PATCH 3/6] Add test for parseUrl handling of data URLs --- feature/xhr/instrument/parse-url.js | 1 + tests/browser/xhr/parse-url.browser.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/feature/xhr/instrument/parse-url.js b/feature/xhr/instrument/parse-url.js index ae1b24efd..91e74055d 100644 --- a/feature/xhr/instrument/parse-url.js +++ b/feature/xhr/instrument/parse-url.js @@ -10,6 +10,7 @@ module.exports = function parseUrl (url) { return stringsToParsedUrls[url] } + // Return if URL is a data URL, parseUrl assumes urls are http/https if (url.indexOf('data:') === 0) { return { protocol: 'data' diff --git a/tests/browser/xhr/parse-url.browser.js b/tests/browser/xhr/parse-url.browser.js index 0ebf37e49..c21af8c15 100644 --- a/tests/browser/xhr/parse-url.browser.js +++ b/tests/browser/xhr/parse-url.browser.js @@ -79,6 +79,12 @@ function xhr_tests () { port: location.port, sameOrigin: true } + }, + { + url: 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==', + results: { + protocol: 'data' + } } ] From b01f905e78f4648532ad937015a1b48d82eb6ea6 Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Mon, 27 Dec 2021 16:04:28 -0800 Subject: [PATCH 4/6] Handle parseUrl case where URL is undefined --- feature/xhr/instrument/parse-url.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/xhr/instrument/parse-url.js b/feature/xhr/instrument/parse-url.js index 91e74055d..004353c40 100644 --- a/feature/xhr/instrument/parse-url.js +++ b/feature/xhr/instrument/parse-url.js @@ -11,7 +11,7 @@ module.exports = function parseUrl (url) { } // Return if URL is a data URL, parseUrl assumes urls are http/https - if (url.indexOf('data:') === 0) { + if ((url || '').indexOf('data:') === 0) { return { protocol: 'data' } From c64d551f99cb7cf4ade4fe466a3312181bc22243 Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Wed, 29 Dec 2021 16:07:49 -0800 Subject: [PATCH 5/6] Skip browsers incompatible with data URL XHR requests --- tests/browser/xhr/data-url.browser.js | 34 ++++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/tests/browser/xhr/data-url.browser.js b/tests/browser/xhr/data-url.browser.js index c14b41c6c..4d0383503 100644 --- a/tests/browser/xhr/data-url.browser.js +++ b/tests/browser/xhr/data-url.browser.js @@ -3,34 +3,44 @@ * SPDX-License-Identifier: Apache-2.0 */ -const test = require('../../../tools/jil/browser-test') -const ee = require('ee') -const handleEE = ee.get('handle') +var test = require('../../../tools/jil/browser-test') +var ee = require('ee') +var handleEE = ee.get('handle') -const hasXhr = window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.addEventListener +var hasXhr = window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.addEventListener require('../../../feature/xhr/instrument') test('XHR request for Data URL does not generate telemetry', function(t) { if (!hasXhr) { - t.pass('xhr is not supported in this browser') + t.skip('XHR is not supported in this browser') t.end() return } + ee.addEventListener('send-xhr-start', validate) handleEE.addEventListener('xhr', failCase) - ee.addEventListener('send-xhr-start', validate) + try { + var xhr = new XMLHttpRequest() + xhr.open('GET', 'data:,dataUrl') + xhr.send() + } catch (e) { + ee.removeEventListener('send-xhr-start', validate) + handleEE.removeEventListener('xhr', failCase) + + t.skip('XHR with data URL not supported in this browser') + t.end() + return + } - var xhr = new XMLHttpRequest() - xhr.open('GET', 'data:,data-uri') - xhr.send() + t.plan(2) function validate (args, xhr) { t.equals(this.params.protocol, 'data', 'XHR Data URL request recorded') setTimeout(() => { - handleEE.removeEventListener('xhr', failCase) ee.removeEventListener('send-xhr-start', validate) + handleEE.removeEventListener('xhr', failCase) t.pass('XHR Data URL request did not generate telemetry') t.end() @@ -38,8 +48,10 @@ test('XHR request for Data URL does not generate telemetry', function(t) { } function failCase (params, metrics, start) { - t.fail('XHR request for Data URL should not generate telemetry') + ee.removeEventListener('send-xhr-start', validate) handleEE.removeEventListener('xhr', failCase) + + t.fail('XHR Data URL request should not generate telemetry') } }) From 1031a8ab8574779f3b85ebcbbb0f9e00bfc915c3 Mon Sep 17 00:00:00 2001 From: aubreymasten Date: Thu, 30 Dec 2021 11:36:43 -0800 Subject: [PATCH 6/6] Record supportability metric when excluding dataUrl request --- feature/xhr/instrument/index.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/feature/xhr/instrument/index.js b/feature/xhr/instrument/index.js index 64921643d..7dce567a9 100644 --- a/feature/xhr/instrument/index.js +++ b/feature/xhr/instrument/index.js @@ -19,6 +19,7 @@ var ffVersion = require('../../../loader/firefox-version') var dataSize = require('ds') var responseSizeFromXhr = require('./response-size') var eventListenerOpts = require('event-listener-opts') +var recordSupportability = require('metrics').recordSupportability var origRequest = NREUM.o.REQ var origXHR = window.XMLHttpRequest @@ -283,7 +284,10 @@ ee.on('fetch-done', function (err, res) { } // Do not generate telemetry for Data URL requests because they don't behave like other network requests - if (this.params.protocol === 'data') return + if (this.params.protocol === 'data') { + recordSupportability('Ajax/DataUrl/Excluded') + return + } this.params.status = res ? res.status : 0 @@ -315,7 +319,10 @@ function end (xhr) { } // Do not generate telemetry for Data URL requests because they don't behave like other network requests - if (params.protocol && params.protocol === 'data') return + if (params.protocol && params.protocol === 'data') { + recordSupportability('Ajax/DataUrl/Excluded') + return + } if (params.aborted) return metrics.duration = loader.now() - this.startTime