From c054741e846455b007dac66e7028b7e2b7d8a615 Mon Sep 17 00:00:00 2001 From: Volodymyr Malyhin Date: Thu, 3 Oct 2024 15:40:47 +0300 Subject: [PATCH 1/5] feat(ilc): disable newrelic for lde in ilc --- ilc/newrelic.js | 49 ---------------------- ilc/server/tailor/configs-injector.js | 8 ++-- ilc/server/tailor/configs-injector.spec.js | 45 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 54 deletions(-) delete mode 100644 ilc/newrelic.js diff --git a/ilc/newrelic.js b/ilc/newrelic.js deleted file mode 100644 index c7d3f270..00000000 --- a/ilc/newrelic.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -// See: https://docs.newrelic.com/docs/agents/nodejs-agent/installation-configuration/nodejs-agent-configuration - -const config = require('config'); - -exports.config = { - agent_enabled: config.get('newrelic.licenseKey') !== null || config.get('newrelic.standardLicenseKey') !== null, - app_name: [ - config.get('newrelic.appName') !== null - ? config.get('newrelic.appName') - : `ILC${process.env.NODE_ENV ? '@' + process.env.NODE_ENV : ''}`, - ], - license_key: config.get('newrelic.licenseKey') || config.get('newrelic.standardLicenseKey'), - logging: { - level: 'info', - logging: true, - filepath: 'stdout', - }, - allow_all_headers: true, - attributes: { - /** - * Prefix of attributes to exclude from all destinations. Allows * as wildcard - * at end. - * - * NOTE: If excluding headers, they must be in camelCase form to be filtered. - * - * @env NEW_RELIC_ATTRIBUTES_EXCLUDE - */ - exclude: [ - 'request.headers.cookie', - 'request.headers.authorization', - 'request.headers.proxyAuthorization', - 'request.headers.setCookie*', - 'request.headers.x*', - 'response.headers.cookie', - 'response.headers.authorization', - 'response.headers.proxyAuthorization', - 'response.headers.setCookie*', - 'response.headers.x*', - ], - }, - error_collector: { - ignore_status_codes: [400, 404, 405], - }, - rules: { - ignore: ['^/ping$', '^/api/v1/monitor/ping/.*$'], - }, -}; diff --git a/ilc/server/tailor/configs-injector.js b/ilc/server/tailor/configs-injector.js index be6b09fe..1965b967 100644 --- a/ilc/server/tailor/configs-injector.js +++ b/ilc/server/tailor/configs-injector.js @@ -54,13 +54,15 @@ module.exports = class ConfigsInjector { registryConfig.settings?.i18n, ); + const newRelicScript = + !this.#nrAutomaticallyInjectClientScript || request.ldeRelated ? '' : this.#getNewRelicScript(); const headHtmlContent = this.#wrapWithIgnoreDuringParsing( //...routeAssets.scriptLinks, this.#getIlcState(request), this.#getSPAConfig(registryConfig), ``, this.#wrapWithAsyncScriptTag(this.#getClientjsUrl()), - this.#getNewRelicScript(), + newRelicScript, hrefLangHtml, canonicalTagHtml, ); @@ -234,10 +236,6 @@ module.exports = class ConfigsInjector { // So it is much easier to achieve needed outcome by modifying template. // Right now gently backward compatibility is maintained, so everyone who expects NR to be injected in browser will get it. #getNewRelicScript = () => { - if (!this.#nrAutomaticallyInjectClientScript) { - return ''; - } - let nrCode = this.#newrelic.getBrowserTimingHeader(); if (this.#nrCustomClientJsWrapper === null || !nrCode) { return nrCode; diff --git a/ilc/server/tailor/configs-injector.spec.js b/ilc/server/tailor/configs-injector.spec.js index 5e773ac1..552b8edd 100644 --- a/ilc/server/tailor/configs-injector.spec.js +++ b/ilc/server/tailor/configs-injector.spec.js @@ -2,6 +2,7 @@ const chai = require('chai'); const sinon = require('sinon'); const _ = require('lodash'); const _fp = require('lodash/fp'); +const LZUTF8 = require('lzutf8'); const { context } = require('../context/context'); const ConfigsInjector = require('./configs-injector'); @@ -417,5 +418,49 @@ describe('configs injector', () => { }, ); }); + it('should exclude New Relic script if ILC-overrideConfig cookie is present', () => { + const overrideConfig = JSON.stringify({ someKey: 'someValue' }); + const encodedOverrideConfig = 'LZUTF8:' + LZUTF8.encodeBase64(LZUTF8.compress(overrideConfig)); + + context.run( + { + request: { + raw: { + url: 'test/a?test=15', + connection: { + encrypted: true, + }, + }, + hostname: 'test.com', + headers: { + cookie: `ILC-overrideConfig=${encodedOverrideConfig}`, + }, + }, + }, + () => { + const browserTimingHeader = ``; + newrelic.getBrowserTimingHeader.withArgs().returns(browserTimingHeader); + const configsInjector = new ConfigsInjector(newrelic); + const request = { registryConfig, ilcState: { locale: 'en-US' }, ldeRelated: true }; + const template = { + styleRefs: [], + content: + '' + + '' + + '' + + 'Configs Injector`s test' + + '' + + '' + + '' + + '' + + '
Hi there! I am content.
' + + '' + + '', + }; + const result = configsInjector.inject(request, template, { slots, reqUrl: '/test/route?a=15' }); + chai.expect(result).to.not.include(browserTimingHeader); + }, + ); + }); }); }); From a97398c56029a50b474e133afd3dbec90146d4da Mon Sep 17 00:00:00 2001 From: Volodymyr Malyhin Date: Thu, 3 Oct 2024 15:49:23 +0300 Subject: [PATCH 2/5] chore(ilc): revert file --- ilc/newrelic.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 ilc/newrelic.js diff --git a/ilc/newrelic.js b/ilc/newrelic.js new file mode 100644 index 00000000..c7d3f270 --- /dev/null +++ b/ilc/newrelic.js @@ -0,0 +1,49 @@ +'use strict'; + +// See: https://docs.newrelic.com/docs/agents/nodejs-agent/installation-configuration/nodejs-agent-configuration + +const config = require('config'); + +exports.config = { + agent_enabled: config.get('newrelic.licenseKey') !== null || config.get('newrelic.standardLicenseKey') !== null, + app_name: [ + config.get('newrelic.appName') !== null + ? config.get('newrelic.appName') + : `ILC${process.env.NODE_ENV ? '@' + process.env.NODE_ENV : ''}`, + ], + license_key: config.get('newrelic.licenseKey') || config.get('newrelic.standardLicenseKey'), + logging: { + level: 'info', + logging: true, + filepath: 'stdout', + }, + allow_all_headers: true, + attributes: { + /** + * Prefix of attributes to exclude from all destinations. Allows * as wildcard + * at end. + * + * NOTE: If excluding headers, they must be in camelCase form to be filtered. + * + * @env NEW_RELIC_ATTRIBUTES_EXCLUDE + */ + exclude: [ + 'request.headers.cookie', + 'request.headers.authorization', + 'request.headers.proxyAuthorization', + 'request.headers.setCookie*', + 'request.headers.x*', + 'response.headers.cookie', + 'response.headers.authorization', + 'response.headers.proxyAuthorization', + 'response.headers.setCookie*', + 'response.headers.x*', + ], + }, + error_collector: { + ignore_status_codes: [400, 404, 405], + }, + rules: { + ignore: ['^/ping$', '^/api/v1/monitor/ping/.*$'], + }, +}; From 81edaddde93ef6f6a4b4cee1a317960c106f62c9 Mon Sep 17 00:00:00 2001 From: Volodymyr Malyhin Date: Mon, 7 Oct 2024 12:53:56 +0300 Subject: [PATCH 3/5] feat: add tags for removing parts from template --- ilc/package-lock.json | 9 +++++---- ilc/package.json | 2 +- ilc/server/tailor/configs-injector.js | 19 ++++++++++++++++--- ilc/server/tailor/configs-injector.spec.js | 14 ++++++++++---- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/ilc/package-lock.json b/ilc/package-lock.json index 19df79b8..872a2baf 100644 --- a/ilc/package-lock.json +++ b/ilc/package-lock.json @@ -10,7 +10,7 @@ "license": "Apache-2.0", "dependencies": { "@namecheap/error-extender": "^2.2.1", - "@namecheap/tailorx": "^8.1.0", + "@namecheap/tailorx": "^8.2.0", "@newrelic/native-metrics": "^11.0.0", "agentkeepalive": "^4.5.0", "axios": "^1.7.7", @@ -2195,9 +2195,10 @@ "integrity": "sha512-GeFZT8ntXN7N91jyHy7qEw4Kq0v66kV/7+/EQJHHsdzbko44wtrDvr+Mj6Td9soqlZGQz8VoOUa9XrHSauVcLA==" }, "node_modules/@namecheap/tailorx": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@namecheap/tailorx/-/tailorx-8.1.0.tgz", - "integrity": "sha512-TSCfaKfUd14QQkZrZHYIP/vj5zONxhCNtpTkpd15BN0XPl2idHwJFBDaNgKqGh/iZiHesCcXMsM6sQRIgizmKg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@namecheap/tailorx/-/tailorx-8.2.0.tgz", + "integrity": "sha512-RAeOeaiw1btqowbkc5BfklXGBFUw4R4SkVCFNAVxEj9Hc/qaeo1SnDF99MI8nTiixefaZCWvyHhcp8R0/iwO3A==", + "license": "Apache-2.0", "dependencies": { "@namecheap/error-extender": "^2.0.0", "agentkeepalive": "^4.5.0", diff --git a/ilc/package.json b/ilc/package.json index 917d067b..9a1ed481 100644 --- a/ilc/package.json +++ b/ilc/package.json @@ -21,7 +21,7 @@ "license": "Apache-2.0", "dependencies": { "@namecheap/error-extender": "^2.2.1", - "@namecheap/tailorx": "^8.1.0", + "@namecheap/tailorx": "^8.2.0", "@newrelic/native-metrics": "^11.0.0", "agentkeepalive": "^4.5.0", "axios": "^1.7.7", diff --git a/ilc/server/tailor/configs-injector.js b/ilc/server/tailor/configs-injector.js index 1965b967..23a7ecef 100644 --- a/ilc/server/tailor/configs-injector.js +++ b/ilc/server/tailor/configs-injector.js @@ -54,15 +54,13 @@ module.exports = class ConfigsInjector { registryConfig.settings?.i18n, ); - const newRelicScript = - !this.#nrAutomaticallyInjectClientScript || request.ldeRelated ? '' : this.#getNewRelicScript(); const headHtmlContent = this.#wrapWithIgnoreDuringParsing( //...routeAssets.scriptLinks, this.#getIlcState(request), this.#getSPAConfig(registryConfig), ``, this.#wrapWithAsyncScriptTag(this.#getClientjsUrl()), - newRelicScript, + this.#getNewRelicScript(), hrefLangHtml, canonicalTagHtml, ); @@ -75,6 +73,10 @@ module.exports = class ConfigsInjector { request.styleRefs = this.#getRouteStyleRefsToPreload(registryConfig.apps, slots, template.styleRefs); + if (request.ldeRelated) { + document = this.#wrapTagsToRemove(document, /]*>\s*;window\.NREUM[\s\S]*?<\/script>/g); + } + return document; } @@ -236,6 +238,10 @@ module.exports = class ConfigsInjector { // So it is much easier to achieve needed outcome by modifying template. // Right now gently backward compatibility is maintained, so everyone who expects NR to be injected in browser will get it. #getNewRelicScript = () => { + if (!this.#nrAutomaticallyInjectClientScript) { + return ''; + } + let nrCode = this.#newrelic.getBrowserTimingHeader(); if (this.#nrCustomClientJsWrapper === null || !nrCode) { return nrCode; @@ -244,4 +250,11 @@ module.exports = class ConfigsInjector { nrCode = nrCode.replace(/(.*)<\/script\s*>/s, '$1'); return this.#nrCustomClientJsWrapper.replace('%CONTENT%', nrCode); }; + + #wrapWithRemoveBeforeParsing = (content) => + `${content}`; + + #wrapTagsToRemove(content, regex) { + return content.replace(regex, (match) => this.#wrapWithRemoveBeforeParsing(match)); + } }; diff --git a/ilc/server/tailor/configs-injector.spec.js b/ilc/server/tailor/configs-injector.spec.js index 552b8edd..af4196b6 100644 --- a/ilc/server/tailor/configs-injector.spec.js +++ b/ilc/server/tailor/configs-injector.spec.js @@ -418,7 +418,7 @@ describe('configs injector', () => { }, ); }); - it('should exclude New Relic script if ILC-overrideConfig cookie is present', () => { + it('should add remove new relic wrap tags if ILC-overrideConfig cookie is present', () => { const overrideConfig = JSON.stringify({ someKey: 'someValue' }); const encodedOverrideConfig = 'LZUTF8:' + LZUTF8.encodeBase64(LZUTF8.compress(overrideConfig)); @@ -438,8 +438,12 @@ describe('configs injector', () => { }, }, () => { - const browserTimingHeader = ``; - newrelic.getBrowserTimingHeader.withArgs().returns(browserTimingHeader); + const nrHeader = ``; + const expectedHeader = `${nrHeader}` const configsInjector = new ConfigsInjector(newrelic); const request = { registryConfig, ilcState: { locale: 'en-US' }, ldeRelated: true }; const template = { @@ -447,6 +451,7 @@ describe('configs injector', () => { content: '' + '' + + nrHeader + '' + 'Configs Injector`s test' + '' + @@ -457,8 +462,9 @@ describe('configs injector', () => { '' + '', }; + const result = configsInjector.inject(request, template, { slots, reqUrl: '/test/route?a=15' }); - chai.expect(result).to.not.include(browserTimingHeader); + chai.expect(result).to.include(expectedHeader); }, ); }); From 695c75e37af13c854bd8bae27518b3c93287d9a8 Mon Sep 17 00:00:00 2001 From: Volodymyr Malyhin Date: Mon, 7 Oct 2024 13:05:03 +0300 Subject: [PATCH 4/5] chore(ilc): fix lint --- ilc/server/tailor/configs-injector.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ilc/server/tailor/configs-injector.spec.js b/ilc/server/tailor/configs-injector.spec.js index af4196b6..ab39f0a3 100644 --- a/ilc/server/tailor/configs-injector.spec.js +++ b/ilc/server/tailor/configs-injector.spec.js @@ -443,7 +443,7 @@ describe('configs injector', () => { ;NREUM.loader_config={accountID:"1111",trustKey:"1111",agentID:"1111",licenseKey:"1111",applicationID:"1111"}; ;NREUM.info={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net",licenseKey:"1111",applicationID:"1111",sa:1};`; - const expectedHeader = `${nrHeader}` + const expectedHeader = `${nrHeader}`; const configsInjector = new ConfigsInjector(newrelic); const request = { registryConfig, ilcState: { locale: 'en-US' }, ldeRelated: true }; const template = { From f127d4968a697a09f32015fba849ffcd93b07180 Mon Sep 17 00:00:00 2001 From: Volodymyr Malyhin Date: Mon, 7 Oct 2024 18:54:46 +0300 Subject: [PATCH 5/5] feat(ilc): add tag for removing production related scripts --- ilc/server/tailor/configs-injector.js | 10 ++++------ ilc/server/tailor/configs-injector.spec.js | 9 ++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/ilc/server/tailor/configs-injector.js b/ilc/server/tailor/configs-injector.js index 23a7ecef..36223a90 100644 --- a/ilc/server/tailor/configs-injector.js +++ b/ilc/server/tailor/configs-injector.js @@ -11,6 +11,7 @@ module.exports = class ConfigsInjector { #cdnUrl; #jsInjectionPlaceholder = ''; #cssInjectionPlaceholder = ''; + #markedProdTags = /.*?/gims; constructor(newrelic, cdnUrl = null, nrCustomClientJsWrapper = null, nrAutomaticallyInjectClientScript = true) { this.#newrelic = newrelic; @@ -74,7 +75,7 @@ module.exports = class ConfigsInjector { request.styleRefs = this.#getRouteStyleRefsToPreload(registryConfig.apps, slots, template.styleRefs); if (request.ldeRelated) { - document = this.#wrapTagsToRemove(document, /]*>\s*;window\.NREUM[\s\S]*?<\/script>/g); + document = this.#removeProdTags(document); } return document; @@ -251,10 +252,7 @@ module.exports = class ConfigsInjector { return this.#nrCustomClientJsWrapper.replace('%CONTENT%', nrCode); }; - #wrapWithRemoveBeforeParsing = (content) => - `${content}`; - - #wrapTagsToRemove(content, regex) { - return content.replace(regex, (match) => this.#wrapWithRemoveBeforeParsing(match)); + #removeProdTags(content) { + return content.replace(this.#markedProdTags, ''); } }; diff --git a/ilc/server/tailor/configs-injector.spec.js b/ilc/server/tailor/configs-injector.spec.js index ab39f0a3..4d3df967 100644 --- a/ilc/server/tailor/configs-injector.spec.js +++ b/ilc/server/tailor/configs-injector.spec.js @@ -418,7 +418,7 @@ describe('configs injector', () => { }, ); }); - it('should add remove new relic wrap tags if ILC-overrideConfig cookie is present', () => { + it('should remove marked tags for LDE if cookie is present', () => { const overrideConfig = JSON.stringify({ someKey: 'someValue' }); const encodedOverrideConfig = 'LZUTF8:' + LZUTF8.encodeBase64(LZUTF8.compress(overrideConfig)); @@ -438,12 +438,11 @@ describe('configs injector', () => { }, }, () => { - const nrHeader = ``; - const expectedHeader = `${nrHeader}`; + ;NREUM.info={beacon:"bam.nr-data.net",errorBeacon:"bam.nr-data.net",licenseKey:"1111",applicationID:"1111",sa:1};`; const configsInjector = new ConfigsInjector(newrelic); const request = { registryConfig, ilcState: { locale: 'en-US' }, ldeRelated: true }; const template = { @@ -464,7 +463,7 @@ describe('configs injector', () => { }; const result = configsInjector.inject(request, template, { slots, reqUrl: '/test/route?a=15' }); - chai.expect(result).to.include(expectedHeader); + chai.expect(result).to.not.include(nrHeader); }, ); });