diff --git a/.yarn/cache/@esbuild-darwin-x64-npm-0.21.5-491c2ae06c-10.zip b/.yarn/cache/@esbuild-darwin-x64-npm-0.21.5-491c2ae06c-10.zip deleted file mode 100644 index c29febdf513..00000000000 Binary files a/.yarn/cache/@esbuild-darwin-x64-npm-0.21.5-491c2ae06c-10.zip and /dev/null differ diff --git a/.yarn/cache/@next-swc-darwin-x64-npm-14.2.10-a1396b1353-10.zip b/.yarn/cache/@next-swc-linux-x64-gnu-npm-14.2.10-c8787ddfc6-10.zip similarity index 73% rename from .yarn/cache/@next-swc-darwin-x64-npm-14.2.10-a1396b1353-10.zip rename to .yarn/cache/@next-swc-linux-x64-gnu-npm-14.2.10-c8787ddfc6-10.zip index 1dc6672a331..d606f24cbe2 100644 Binary files a/.yarn/cache/@next-swc-darwin-x64-npm-14.2.10-a1396b1353-10.zip and b/.yarn/cache/@next-swc-linux-x64-gnu-npm-14.2.10-c8787ddfc6-10.zip differ diff --git a/.yarn/cache/@types-jsdom-npm-21.1.6-29114a659c-423fcaf3ec.zip b/.yarn/cache/@types-jsdom-npm-21.1.6-29114a659c-423fcaf3ec.zip deleted file mode 100644 index 99d0aaef028..00000000000 Binary files a/.yarn/cache/@types-jsdom-npm-21.1.6-29114a659c-423fcaf3ec.zip and /dev/null differ diff --git a/.yarn/cache/@types-jsdom-npm-21.1.7-b9d35cbe67-a5ee54aec8.zip b/.yarn/cache/@types-jsdom-npm-21.1.7-b9d35cbe67-a5ee54aec8.zip new file mode 100644 index 00000000000..ac46f8a03c7 Binary files /dev/null and b/.yarn/cache/@types-jsdom-npm-21.1.7-b9d35cbe67-a5ee54aec8.zip differ diff --git a/.yarn/cache/@types-node-fetch-npm-2.6.11-55289bb1a8-c416df8f18.zip b/.yarn/cache/@types-node-fetch-npm-2.6.11-55289bb1a8-c416df8f18.zip new file mode 100644 index 00000000000..cfe1c608c8d Binary files /dev/null and b/.yarn/cache/@types-node-fetch-npm-2.6.11-55289bb1a8-c416df8f18.zip differ diff --git a/.yarn/cache/fsevents-patch-6b67494872-10.zip b/.yarn/cache/fsevents-patch-6b67494872-10.zip deleted file mode 100644 index 9887ada72d9..00000000000 Binary files a/.yarn/cache/fsevents-patch-6b67494872-10.zip and /dev/null differ diff --git a/.yarn/cache/http-proxy-middleware-npm-2.0.6-3bb17658ee-768e7ae5a4.zip b/.yarn/cache/http-proxy-middleware-npm-2.0.7-886a673e85-4a51bf612b.zip similarity index 80% rename from .yarn/cache/http-proxy-middleware-npm-2.0.6-3bb17658ee-768e7ae5a4.zip rename to .yarn/cache/http-proxy-middleware-npm-2.0.7-886a673e85-4a51bf612b.zip index 91514b9ef9e..d5995b6e9bf 100644 Binary files a/.yarn/cache/http-proxy-middleware-npm-2.0.6-3bb17658ee-768e7ae5a4.zip and b/.yarn/cache/http-proxy-middleware-npm-2.0.7-886a673e85-4a51bf612b.zip differ diff --git a/.yarn/cache/isomorphic-fetch-npm-3.0.0-bce711adff-568fe03075.zip b/.yarn/cache/isomorphic-fetch-npm-3.0.0-bce711adff-568fe03075.zip new file mode 100644 index 00000000000..cd2103d01c4 Binary files /dev/null and b/.yarn/cache/isomorphic-fetch-npm-3.0.0-bce711adff-568fe03075.zip differ diff --git a/.yarn/cache/jake-npm-10.8.7-1caf9b4534-ad1cfe3988.zip b/.yarn/cache/jake-npm-10.9.2-3bf2173aed-3be324708f.zip similarity index 67% rename from .yarn/cache/jake-npm-10.8.7-1caf9b4534-ad1cfe3988.zip rename to .yarn/cache/jake-npm-10.9.2-3bf2173aed-3be324708f.zip index 71acfb88a61..5acb4f3a25f 100644 Binary files a/.yarn/cache/jake-npm-10.8.7-1caf9b4534-ad1cfe3988.zip and b/.yarn/cache/jake-npm-10.9.2-3bf2173aed-3be324708f.zip differ diff --git a/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-a749888789.zip b/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-a749888789.zip deleted file mode 100644 index 4af36001b41..00000000000 Binary files a/.yarn/cache/micromatch-npm-4.0.5-cfab5d7669-a749888789.zip and /dev/null differ diff --git a/.yarn/cache/micromatch-npm-4.0.8-c9570e4aca-6bf2a01672.zip b/.yarn/cache/micromatch-npm-4.0.8-c9570e4aca-6bf2a01672.zip new file mode 100644 index 00000000000..f8ac6b5f61d Binary files /dev/null and b/.yarn/cache/micromatch-npm-4.0.8-c9570e4aca-6bf2a01672.zip differ diff --git a/.yarn/cache/node-fetch-npm-2.6.12-48619ce9d6-370ed4d906.zip b/.yarn/cache/node-fetch-npm-2.6.12-48619ce9d6-370ed4d906.zip new file mode 100644 index 00000000000..35cf218170d Binary files /dev/null and b/.yarn/cache/node-fetch-npm-2.6.12-48619ce9d6-370ed4d906.zip differ diff --git a/.yarn/cache/whatwg-fetch-npm-3.6.20-a6f79b98c4-2b4ed92acd.zip b/.yarn/cache/whatwg-fetch-npm-3.6.20-a6f79b98c4-2b4ed92acd.zip new file mode 100644 index 00000000000..8c78833540c Binary files /dev/null and b/.yarn/cache/whatwg-fetch-npm-3.6.20-a6f79b98c4-2b4ed92acd.zip differ diff --git a/package.json b/package.json index e0c3146d44d..f583698ffac 100644 --- a/package.json +++ b/package.json @@ -45,14 +45,14 @@ "cypress:adhoc": "yarn cypress:interactive -- --project ./AdHocCypress/.", "setupDevEnv": "cp envConfig/local.env .env && rm -rf envConfig/secret.env && ./scripts/checkSecretEnvVariables.sh", "dependencyFreshness": "node ./scripts/dependencyFreshness", - "dev": "yarn setupDevEnv && rm -rf build && run-p webpack:dev:client webpack:dev:server", "esmDependencyCheck": "node ./scripts/esmDependencyCheck.js", + "dev": "yarn setupDevEnv && rm -rf build && NODE_OPTIONS=--no-experimental-fetch run-p webpack:dev:client webpack:dev:server", "lighthouse": "./scripts/lighthouseRun.sh", "mostReadAndWatchedCollectionData": "node ./scripts/mostReadAndWatchedCollectionData", "postshrinkwrap": "test -z $CI && ./scripts/packagelockHttps.sh; git update-index --assume-unchanged .env", "prepare": "husky install", "preinstall": "node scripts/check-package-manager.js", - "start": "NODE_ENV=production node --max-old-space-size=3500 build/server.js", + "start": "NODE_ENV=production node --no-experimental-fetch --max-old-space-size=3500 build/server.js", "stop": "./scripts/killApp.sh", "storybook": "node .storybook/buildFontPreloads && storybook dev -p 9001 -c .storybook", "test": "yarn build && yarn test:local", @@ -109,6 +109,7 @@ "helmet": "7.1.0", "helmet-csp": "4.0.0", "intersection-observer": "0.12.2", + "isomorphic-fetch": "3.0.0", "jalaali-js": "1.2.7", "js-cookie": "3.0.5", "lru-cache": "11.0.1", @@ -124,7 +125,6 @@ "react-lazyload": "3.2.1", "react-router-config": "5.1.1", "react-router-dom": "5.3.4", - "undici": "6.20.1", "url-parse": "1.5.10", "uuid": "8.3.2", "winston": "patch:winston@3.8.2#./patches/winston-file-descriptor.patch" @@ -182,6 +182,7 @@ "@types/js-cookie": "^3.0.3", "@types/jsdom": "^21.0.0", "@types/loadable__component": "5.13.9", + "@types/node-fetch": "^2.6.11", "@types/ramda": "0.30.0", "@types/react": "18.3.3", "@types/react-dom": "18.3.1", @@ -234,6 +235,7 @@ "minimist": "1.2.8", "mkdirp": "3.0.1", "mocha-junit-reporter": "2.2.1", + "node-fetch": "2.6.12", "npm-run-all2": "6.2.2", "prettier": "3.2.5", "retry": "0.13.1", diff --git a/scripts/ampHtmlValidator/index.js b/scripts/ampHtmlValidator/index.js index 8730cd91076..8ece13dfcb8 100644 --- a/scripts/ampHtmlValidator/index.js +++ b/scripts/ampHtmlValidator/index.js @@ -1,4 +1,5 @@ /* eslint-disable no-console */ +const fetch = require('isomorphic-fetch'); const amphtmlValidator = require('amphtml-validator'); const { getPageUrls } = require('../../cypress/support/helpers/getPageUrls'); diff --git a/scripts/ampHtmlValidator/index.test.js b/scripts/ampHtmlValidator/index.test.js index 8aeddf5e303..618e6657a49 100644 --- a/scripts/ampHtmlValidator/index.test.js +++ b/scripts/ampHtmlValidator/index.test.js @@ -1,3 +1,6 @@ +const fetch = require('isomorphic-fetch'); + +jest.mock('isomorphic-fetch'); fetch.mockImplementation(() => ({ text: () => '' })); const log = jest.spyOn(global.console, 'log'); log.mockImplementation(jest.fn); diff --git a/scripts/bundleSize/bundleSizeConfig.js b/scripts/bundleSize/bundleSizeConfig.js index bf46927739f..398a8d628fd 100644 --- a/scripts/bundleSize/bundleSizeConfig.js +++ b/scripts/bundleSize/bundleSizeConfig.js @@ -7,5 +7,5 @@ * We are allowing a variance of -5 on `MIN_SIZE` and +5 on `MAX_SIZE` to avoid the need for frequent changes, as bundle sizes can fluctuate */ -export const MIN_SIZE = 635 - 5; -export const MAX_SIZE = 1175 + 5; +export const MIN_SIZE = 646 - 5; +export const MAX_SIZE = 1186 + 5; diff --git a/scripts/dependencyFreshness.js b/scripts/dependencyFreshness.js index 2bf62743bc1..fc615a22b76 100644 --- a/scripts/dependencyFreshness.js +++ b/scripts/dependencyFreshness.js @@ -1,6 +1,7 @@ /* eslint-disable no-console */ const { exec } = require('child_process'); const fs = require('fs'); +const fetch = require('node-fetch'); const { dependencies, devDependencies } = require('../package.json'); const allDependencies = { ...dependencies, ...devDependencies }; diff --git a/scripts/linkeyTest.js b/scripts/linkeyTest.js index f335d244cf7..38e2cfa78ab 100644 --- a/scripts/linkeyTest.js +++ b/scripts/linkeyTest.js @@ -1,3 +1,5 @@ +import fetch from 'node-fetch'; + /* eslint-disable no-undef */ const getServiceName = serviceConfig => { if (serviceConfig.default) { diff --git a/scripts/mostReadAndWatchedCollectionData.js b/scripts/mostReadAndWatchedCollectionData.js index 07156725639..b6763bcf057 100644 --- a/scripts/mostReadAndWatchedCollectionData.js +++ b/scripts/mostReadAndWatchedCollectionData.js @@ -1,7 +1,6 @@ const fs = require('fs'); -const fsPromises = require('fs/promises'); -const { Agent } = require('undici'); -const { createSecureContext } = require('tls'); +const { Agent } = require('https'); +const fetch = require('node-fetch'); const allServices = require('../cypress/support/config/settings')(); const badServices = [ @@ -20,37 +19,18 @@ const services = Object.keys(allServices); console.log('services', services); -const loadCerts = ({ caPath, certChainPath, keyPath }) => - Promise.all([ - fsPromises.readFile(caPath, 'UTF-8'), - fsPromises.readFile(certChainPath, 'UTF-8'), - fsPromises.readFile(keyPath, 'UTF-8'), - ]); - const fetchWithCert = async (url, options) => { - const caPath = process.env.CA_PATH || '/etc/pki/tls/certs/ca-bundle.crt'; - const certChainPath = - process.env.CERT_CHAIN_PATH || '/etc/pki/tls/certs/client.crt'; - const keyPath = process.env.KEY_PATH || '/etc/pki/tls/private/client.key'; - - const [ca, certChain, key] = await loadCerts({ - caPath, - certChainPath, - keyPath, - }); - - return fetch(url, { - dispatcher: new Agent({ - connect: { - secureContext: createSecureContext({ - cert: certChain, - key, - ca, - }), - }, - }), - ...options, - }); + const cert = fs.readFileSync( + process.env.CERT_CHAIN_PATH || '/etc/pki/tls/certs/client.crt', + ); + const ca = fs.readFileSync( + process.env.CA_PATH || '/etc/pki/tls/certs/ca-bundle.crt', + ); + const key = fs.readFileSync( + process.env.KEY_PATH || '/etc/pki/tls/private/client.key', + ); + const agent = new Agent({ cert, ca, key }); + return fetch(url, { agent, ...options }); }; const timeTable = []; @@ -61,9 +41,9 @@ const collectResults = async (link, service, type) => { await fetchWithCert(link).then(response => { if (response.ok) { response.json().then(json => { - const jsondata = 'data' in json ? json.data : json; - if (!('status' in json && json.status === '404')) { - if (!jsondata || !('generated' in jsondata)) { + const jsondata = json.hasOwnProperty('data') ? json.data : json; + if (!(json.hasOwnProperty('status') && json.status === '404')) { + if (!jsondata || !jsondata.hasOwnProperty('generated')) { console.log('json where no data', jsondata); } const generatedDateTime = new Date(jsondata.generated); @@ -72,8 +52,9 @@ const collectResults = async (link, service, type) => { const minutesSinceGenerated = Math.floor( timeDifference / (1000 * 60), ); - const records = - 'items' in jsondata ? jsondata.items : jsondata.records; + const records = jsondata.hasOwnProperty('items') + ? jsondata.items + : jsondata.records; const counts = records .map(record => record.count) .slice(0, 10) @@ -116,7 +97,7 @@ const collectResults = async (link, service, type) => { services .filter(service => !badServices.includes(service)) - .forEach(service => { + .forEach((service, i) => { let serviceToCall = service; if (servicesWithVariants.some(variant => service.includes(variant))) { serviceToCall = service.replace(/([A-Z])/, '_$1').toLowerCase(); diff --git a/scripts/mostReadCollectionTimes.js b/scripts/mostReadCollectionTimes.js index 4aa570e7f72..4618b6bb076 100644 --- a/scripts/mostReadCollectionTimes.js +++ b/scripts/mostReadCollectionTimes.js @@ -1,7 +1,6 @@ const fs = require('fs'); -const fsPromises = require('fs/promises'); -const { Agent } = require('undici'); -const { createSecureContext } = require('tls'); +const { Agent } = require('https'); +const fetch = require('node-fetch'); const allServices = require('../cypress/support/config/settings')(); const badServices = [ @@ -20,38 +19,20 @@ const services = Object.keys(allServices); console.log('services', services); -const loadCerts = ({ caPath, certChainPath, keyPath }) => - Promise.all([ - fsPromises.readFile(caPath, 'UTF-8'), - fsPromises.readFile(certChainPath, 'UTF-8'), - fsPromises.readFile(keyPath, 'UTF-8'), - ]); - const fetchWithCert = async (url, options) => { - const caPath = process.env.CA_PATH || '/etc/pki/tls/certs/ca-bundle.crt'; - const certChainPath = - process.env.CERT_CHAIN_PATH || '/etc/pki/tls/certs/client.crt'; - const keyPath = process.env.KEY_PATH || '/etc/pki/tls/private/client.key'; - - const [ca, certChain, key] = await loadCerts({ - caPath, - certChainPath, - keyPath, - }); - - return fetch(url, { - dispatcher: new Agent({ - connect: { - secureContext: createSecureContext({ - cert: certChain, - key, - ca, - }), - }, - }), - ...options, - }); + const cert = fs.readFileSync( + process.env.CERT_CHAIN_PATH || '/etc/pki/tls/certs/client.crt', + ); + const ca = fs.readFileSync( + process.env.CA_PATH || '/etc/pki/tls/certs/ca-bundle.crt', + ); + const key = fs.readFileSync( + process.env.KEY_PATH || '/etc/pki/tls/private/client.key', + ); + const agent = new Agent({ cert, ca, key }); + return fetch(url, { agent, ...options }); }; + const timeTable = []; let csvContents; @@ -60,9 +41,9 @@ const collectResults = async (link, service, type) => { await fetchWithCert(link).then(response => { if (response.ok) { response.json().then(json => { - const jsondata = 'data' in json ? json.data : json; - if (!('status' in json && json.status === '404')) { - if (!jsondata || !('generated' in jsondata)) { + const jsondata = json.hasOwnProperty('data') ? json.data : json; + if (!(json.hasOwnProperty('status') && json.status === '404')) { + if (!jsondata || !jsondata.hasOwnProperty('generated')) { console.log('json where no data', jsondata); } const generatedDateTime = new Date(jsondata.generated); @@ -71,8 +52,9 @@ const collectResults = async (link, service, type) => { const minutesSinceGenerated = Math.floor( timeDifference / (1000 * 60), ); - const records = - 'items' in jsondata ? jsondata.items : jsondata.records; + const records = jsondata.hasOwnProperty('items') + ? jsondata.items + : jsondata.records; const counts = records .map(record => record.count) .slice(0, 10) @@ -99,23 +81,21 @@ const collectResults = async (link, service, type) => { if (timeTable.length === (services.length - badServices.length) * 2) { csvContents = 'service, type, link, generated, timeSinceGenerated, lastRecordTimeStamp, firstRecordTimeStamp, sequence, totalRecords, rank1, rank2, rank3, rank4, rank5, rank6, rank7, rank8, rank9, rank10'; - timeTable - .sort((a, b) => { + timeTable.sort((a, b) => { if (a.service > b.service) { return 1; } - if (a.service < b.service) { + else if (a.service < b.service) { return -1; } - if (a.type < b.type) { + else if (a.type < b.type) { return -1; } - if (a.type > b.type) { + else if (a.type > b.type) { return 1; } return 0; - }) - .forEach(result => { + }).forEach(result => { csvContents += `\n${result.service},${result.type},${result.link},${result.generated},${result.minutesSinceGenerated},${result.lastRecordTimestamp},${result.firstRecordTimestamp},${result.sequence},${result.totalRecords},${result.counts}`; }); fs.writeFileSync('./mostReadCollectionTimes.csv', csvContents); @@ -131,7 +111,7 @@ const collectResults = async (link, service, type) => { services .filter(service => !badServices.includes(service)) - .forEach(service => { + .forEach((service, i) => { let serviceToCall = service; if (servicesWithVariants.some(variant => service.includes(variant))) { serviceToCall = service.replace(/([A-Z])/, '_$1').toLowerCase(); @@ -159,4 +139,4 @@ const collectResults = async (link, service, type) => { }); await Promise.all(promises); -})(); +})(); \ No newline at end of file diff --git a/src/app/legacy/containers/ConsentBanner/useConsentBanners/setCookieOven.js b/src/app/legacy/containers/ConsentBanner/useConsentBanners/setCookieOven.js index 0b676a867f2..04cd6cfaf1c 100644 --- a/src/app/legacy/containers/ConsentBanner/useConsentBanners/setCookieOven.js +++ b/src/app/legacy/containers/ConsentBanner/useConsentBanners/setCookieOven.js @@ -1,3 +1,4 @@ +import 'isomorphic-fetch'; import path from 'ramda/src/path'; import getCookieOvenEndpoints from './getCookieOvenEndpoints'; diff --git a/src/app/legacy/containers/RadioSchedule/Canonical/index.jsx b/src/app/legacy/containers/RadioSchedule/Canonical/index.jsx index d76f7353bad..d509e0eeaf5 100644 --- a/src/app/legacy/containers/RadioSchedule/Canonical/index.jsx +++ b/src/app/legacy/containers/RadioSchedule/Canonical/index.jsx @@ -1,5 +1,6 @@ import React, { useEffect, useState, useContext } from 'react'; import { useTheme } from '@emotion/react'; +import 'isomorphic-fetch'; import styled from '@emotion/styled'; import moment from 'moment'; import { diff --git a/src/app/lib/analyticsUtils/sendBeacon/index.js b/src/app/lib/analyticsUtils/sendBeacon/index.js index 25f6d3a4afd..f9fce75d4b2 100644 --- a/src/app/lib/analyticsUtils/sendBeacon/index.js +++ b/src/app/lib/analyticsUtils/sendBeacon/index.js @@ -1,6 +1,7 @@ import onClient from '../../utilities/onClient'; import nodeLogger from '../../logger.node'; import { ATI_LOGGING_ERROR } from '../../logger.const'; +import 'isomorphic-fetch'; const logger = nodeLogger(__filename); diff --git a/src/app/models/types/fetch.ts b/src/app/models/types/fetch.ts index eb4b936e1a5..4ca9d42ef22 100644 --- a/src/app/models/types/fetch.ts +++ b/src/app/models/types/fetch.ts @@ -1,7 +1,3 @@ -import { Agent } from 'undici'; - export interface FetchError extends Error { status: number; } - -export type GetAgent = () => Promise; diff --git a/src/app/models/types/initialData.ts b/src/app/models/types/initialData.ts index 403797acd92..da1221bfae3 100644 --- a/src/app/models/types/initialData.ts +++ b/src/app/models/types/initialData.ts @@ -1,4 +1,3 @@ -import { GetAgent } from './fetch'; import { PageTypes, Services, Toggles, Variants } from './global'; export type InitialDataProps = { @@ -7,5 +6,4 @@ export type InitialDataProps = { pageType: PageTypes; variant?: Variants; toggles?: Toggles; - getAgent?: GetAgent; }; diff --git a/src/app/models/types/pageDataParams.ts b/src/app/models/types/pageDataParams.ts index 5b8ec041362..c2bcd04e6c4 100644 --- a/src/app/models/types/pageDataParams.ts +++ b/src/app/models/types/pageDataParams.ts @@ -1,5 +1,5 @@ import { ParsedUrlQuery } from 'querystring'; -import { PageTypes, Services, Variants } from './global'; +import { Services, Variants } from './global'; export default interface PageDataParams extends ParsedUrlQuery { id: string; @@ -9,5 +9,4 @@ export default interface PageDataParams extends ParsedUrlQuery { // eslint-disable-next-line camelcase renderer_env?: string; resolvedUrl: string; - pageType: PageTypes; } diff --git a/src/app/pages/HomePage/index.stories.tsx b/src/app/pages/HomePage/index.stories.tsx index 02244b86452..0244ab14d44 100644 --- a/src/app/pages/HomePage/index.stories.tsx +++ b/src/app/pages/HomePage/index.stories.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react'; import Url from 'url-parse'; import { HOME_PAGE } from '#app/routes/utils/pageTypes'; +import fetch from 'node-fetch'; import { Curation } from '#app/models/types/curationData'; import { Services } from '#app/models/types/global'; import withServicesDecorator from '#storybook/withServicesDecorator'; @@ -43,7 +44,7 @@ const Component = ({ service, variant }: StoryProps) => { useEffect(() => { const loadPageData = async () => { const response = await fetch( - new Url(`data/${service}/homePage/index.json`).toString(), + new Url(`data/${service}/homePage/index.json`), ); const { data } = await response.json(); diff --git a/src/app/pages/MostReadPage/index.stories.jsx b/src/app/pages/MostReadPage/index.stories.jsx index 49a3143b9be..bc851bc629c 100644 --- a/src/app/pages/MostReadPage/index.stories.jsx +++ b/src/app/pages/MostReadPage/index.stories.jsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import fetch from 'node-fetch'; import Url from 'url-parse'; import { BrowserRouter } from 'react-router-dom'; import { MOST_READ_PAGE } from '#app/routes/utils/pageTypes'; diff --git a/src/app/routes/article/getInitialData/index.test.ts b/src/app/routes/article/getInitialData/index.test.ts index de93106ac76..fa07bcb2f8a 100644 --- a/src/app/routes/article/getInitialData/index.test.ts +++ b/src/app/routes/article/getInitialData/index.test.ts @@ -1,4 +1,4 @@ -import { Agent } from 'undici'; +import { Agent } from 'https'; import * as getOnwardsPageData from '../utils/getOnwardsData'; import * as fetchPageData from '../../utils/fetchPageData'; import nodeLogger from '../../../../testHelpers/loggerMock'; @@ -9,13 +9,11 @@ import { ARTICLE_PAGE } from '../../utils/pageTypes'; process.env.BFF_PATH = 'https://mock-bff-path'; -const agent = { - connect: { cert: 'cert', ca: 'ca', key: 'key' }, -} as unknown as Agent; +const agent = { cert: 'cert', ca: 'ca', key: 'key' }; -const mockGetAgent = () => Promise.resolve(agent); - -jest.mock('../../../../server/utilities/getAgent', () => jest.fn(mockGetAgent)); +jest.mock('../../../../server/utilities/getAgent', () => + jest.fn(() => Promise.resolve(agent as unknown as Agent)), +); const bffArticleJson = { data: { @@ -58,7 +56,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -83,7 +80,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -111,7 +107,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -141,7 +136,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o.amp?renderer_env=live', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(getOnwardsPageDataSpy).toBeCalledWith({ @@ -169,7 +163,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o?renderer_env=test', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -197,7 +190,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o?renderer_env=live', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -219,7 +211,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -242,7 +233,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -273,7 +263,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: ARTICLE_PAGE, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -298,7 +287,6 @@ describe('Articles - BFF Fetching', () => { path: '/kyrgyz/articles/c0000000000o', service: 'kyrgyz', pageType: 'article', - getAgent: mockGetAgent, })) as { pageData: Record }; expect(pageData).toHaveProperty('content'); diff --git a/src/app/routes/article/getInitialData/index.ts b/src/app/routes/article/getInitialData/index.ts index 5c50e8f846a..8478f90690a 100644 --- a/src/app/routes/article/getInitialData/index.ts +++ b/src/app/routes/article/getInitialData/index.ts @@ -5,9 +5,10 @@ import getOnwardsPageData from '../utils/getOnwardsData'; import addAnalyticsCounterName from '../utils/addAnalyticsCounterName'; import augmentWithDisclaimer from '../utils/augmentWithDisclaimer'; import { advertisingAllowed, isSfv } from '../utils/paramChecks'; -import { FetchError, GetAgent } from '../../../models/types/fetch'; +import { FetchError } from '../../../models/types/fetch'; import handleError from '../../utils/handleError'; import fetchDataFromBFF from '../../utils/fetchDataFromBFF'; +import getAgent from '../../../../server/utilities/getAgent'; import { BFF_FETCH_ERROR } from '../../../lib/logger.const'; import certsRequired from '../../utils/certsRequired'; @@ -20,7 +21,6 @@ type Props = { variant?: Variants; toggles?: Toggles; isAmp?: boolean; - getAgent: GetAgent; }; const transformPageData = (toggles?: Toggles) => @@ -36,7 +36,6 @@ export default async ({ variant, toggles, isAmp, - getAgent, }: Props) => { try { const { status, json } = await fetchDataFromBFF({ @@ -45,7 +44,6 @@ export default async ({ service, variant, isAmp, - getAgent, }); const agent = certsRequired(pathname) ? await getAgent() : null; diff --git a/src/app/routes/article/utils/getOnwardsData.test.ts b/src/app/routes/article/utils/getOnwardsData.test.ts index 96c6ed8d562..a1fc3e84d6f 100644 --- a/src/app/routes/article/utils/getOnwardsData.test.ts +++ b/src/app/routes/article/utils/getOnwardsData.test.ts @@ -1,4 +1,4 @@ -import { Agent } from 'undici'; +import { Agent } from 'https'; import recommendationsJson from '#data/mundo/recommendations/index.json'; import hasArticleRecommendations from './hasArticleRecommendations'; import getOnwardsPageData from './getOnwardsData'; @@ -6,10 +6,7 @@ import * as fetchPageData from '../../utils/fetchPageData'; jest.mock('./hasArticleRecommendations', () => jest.fn()); -const agent = { - connect: { cert: 'cert', ca: 'ca', key: 'key' }, -} as unknown as Agent; - +const agent = { cert: 'cert', ca: 'ca', key: 'key' } as unknown as Agent; const fetchDataSpy = jest.spyOn(fetchPageData, 'default'); describe('WSOJ data', () => { diff --git a/src/app/routes/article/utils/getOnwardsData.ts b/src/app/routes/article/utils/getOnwardsData.ts index 93d1ca5f332..4624095ff07 100644 --- a/src/app/routes/article/utils/getOnwardsData.ts +++ b/src/app/routes/article/utils/getOnwardsData.ts @@ -1,4 +1,4 @@ -import { Agent } from 'undici'; +import { Agent } from 'https'; import path from 'ramda/src/path'; import isEmpty from 'ramda/src/isEmpty'; diff --git a/src/app/routes/frontPage/getInitialData/index.js b/src/app/routes/frontPage/getInitialData/index.js index 8ac0c08d5ac..c1dc7238802 100644 --- a/src/app/routes/frontPage/getInitialData/index.js +++ b/src/app/routes/frontPage/getInitialData/index.js @@ -26,20 +26,13 @@ const transformJson = pipe( const getRadioScheduleToggle = path(['frontPageRadioSchedule', 'enabled']); const getRadioSchedulePosition = path(['frontPageRadioSchedule', 'value']); -export default async ({ - path: pathname, - service, - variant, - toggles, - getAgent, -}) => { +export default async ({ path: pathname, service, variant, toggles }) => { try { const pageDataPromise = fetchDataFromBFF({ pathname, pageType: CPS_ASSET, // Legacy Front Pages are curated in CPS and fetched from the BFF using pageType = CPS_ASSET and id = service/front_page service, variant, - getAgent, }); const radioScheduleIsEnabled = getRadioScheduleToggle(toggles); diff --git a/src/app/routes/frontPage/getInitialData/index.test.js b/src/app/routes/frontPage/getInitialData/index.test.js index 6a81bb6d406..873f4668ecb 100644 --- a/src/app/routes/frontPage/getInitialData/index.test.js +++ b/src/app/routes/frontPage/getInitialData/index.test.js @@ -14,9 +14,6 @@ jest.mock('../../utils/getConfig', () => jest.fn()); process.env.BFF_PATH = 'https://mock-bff-path'; const agent = { cert: 'cert', ca: 'ca', key: 'key' }; - -const mockGetAgent = () => Promise.resolve(agent); - jest.mock('#server/utilities/getAgent', () => jest.fn(() => Promise.resolve(agent)), ); @@ -42,7 +39,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -62,7 +58,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -86,7 +81,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -108,7 +102,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -130,7 +123,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -156,7 +148,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(nodeLogger.error).toHaveBeenCalledWith(BFF_FETCH_ERROR, { @@ -177,7 +168,6 @@ describe('Front Page - Get Initial Data', () => { service: 'serbian', variant: 'lat', pageType, - getAgent: mockGetAgent, }); expect(pageData.metadata.language).toEqual('sr-Latn'); @@ -205,7 +195,6 @@ describe('Front Page - Get Initial Data', () => { value: 'Features', }, }, - getAgent: mockGetAgent, }); expect(pageData.content.groups.length).toBeTruthy(); @@ -223,7 +212,6 @@ describe('Front Page - Get Initial Data', () => { enabled: false, }, }, - getAgent: mockGetAgent, }); expect(pageData.content.groups.length).toBeTruthy(); @@ -244,7 +232,6 @@ describe('Front Page - Get Initial Data', () => { enabled: true, }, }, - getAgent: mockGetAgent, }); expect(pageData.content.groups.length).toBeTruthy(); diff --git a/src/app/routes/homePage/getInitialData/index.test.ts b/src/app/routes/homePage/getInitialData/index.test.ts index 347dfb1e894..7543b3d7bc5 100644 --- a/src/app/routes/homePage/getInitialData/index.test.ts +++ b/src/app/routes/homePage/getInitialData/index.test.ts @@ -1,4 +1,3 @@ -import { Agent } from 'undici'; import KyrgyzHomeFixture from '#data/kyrgyz/homePage/index.json'; import * as fetchPageData from '../../utils/fetchPageData'; import getInitialData from '.'; @@ -6,13 +5,10 @@ import { HOME_PAGE } from '../../utils/pageTypes'; process.env.BFF_PATH = 'https://mock-bff-path'; -const agent = { - connect: { cert: 'cert', ca: 'ca', key: 'key' }, -} as unknown as Agent; - -const mockGetAgent = jest.fn(() => Promise.resolve(agent)); - -jest.mock('../../../../server/utilities/getAgent', () => jest.fn(mockGetAgent)); +const agent = { cert: 'cert', ca: 'ca', key: 'key' }; +jest.mock('../../../../server/utilities/getAgent', () => + jest.fn(() => Promise.resolve(agent)), +); describe('Home Page - BFF Fetching', () => { const originalEnvironment = process.env.SIMORGH_APP_ENV; @@ -37,7 +33,6 @@ describe('Home Page - BFF Fetching', () => { path: '/kyrgyz/tipohome', service: 'kyrgyz', pageType: 'home', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -62,7 +57,6 @@ describe('Home Page - BFF Fetching', () => { path: '/kyrgyz/tipohome', service: 'kyrgyz', pageType: 'home', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -90,7 +84,6 @@ describe('Home Page - BFF Fetching', () => { path: '/kyrgyz/tipohome', service: 'kyrgyz', pageType: 'home', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ diff --git a/src/app/routes/homePage/getInitialData/index.ts b/src/app/routes/homePage/getInitialData/index.ts index 6da43a2d6ed..804314aea13 100644 --- a/src/app/routes/homePage/getInitialData/index.ts +++ b/src/app/routes/homePage/getInitialData/index.ts @@ -12,7 +12,6 @@ export default async ({ path: pathname, pageType, variant, - getAgent, }: InitialDataProps) => { try { const { status, json } = await fetchDataFromBFF({ @@ -20,7 +19,6 @@ export default async ({ pageType: HOME_PAGE, service, variant, - getAgent, }); const { diff --git a/src/app/routes/mostRead/getInitialData/index.js b/src/app/routes/mostRead/getInitialData/index.js index 9312899f3ec..8687fd505ff 100644 --- a/src/app/routes/mostRead/getInitialData/index.js +++ b/src/app/routes/mostRead/getInitialData/index.js @@ -7,20 +7,13 @@ import nodeLogger from '../../../lib/logger.node'; const logger = nodeLogger(__filename); -export default async ({ - service, - variant, - pageType, - path: pathname, - getAgent, -}) => { +export default async ({ service, variant, pageType, path: pathname }) => { try { const { status, json } = await fetchDataFromBFF({ pathname, service, variant, pageType: MOST_READ_PAGE, - getAgent, }); if (!json?.data) { diff --git a/src/app/routes/mostRead/getInitialData/index.test.js b/src/app/routes/mostRead/getInitialData/index.test.js index 2be8c481963..c546b8b35c5 100644 --- a/src/app/routes/mostRead/getInitialData/index.test.js +++ b/src/app/routes/mostRead/getInitialData/index.test.js @@ -6,9 +6,6 @@ import getInitialData from '.'; process.env.BFF_PATH = 'https://mock-bff-path'; const agent = { cert: 'cert', ca: 'ca', key: 'key' }; - -const mockGetAgent = () => Promise.resolve(agent); - jest.mock('../../../../server/utilities/getAgent', () => jest.fn(() => Promise.resolve(agent)), ); @@ -42,7 +39,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -67,7 +63,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -95,7 +90,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -123,7 +117,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read?renderer_env=test', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -151,7 +144,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read?renderer_env=live', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -177,7 +169,6 @@ describe('MostReadPage - BFF Fetching', () => { path: '/pidgin/popular/read', service: 'pidgin', pageType: MOST_READ_PAGE, - getAgent: mockGetAgent, }); const { pageData } = response; diff --git a/src/app/routes/topic/getInitialData/index.js b/src/app/routes/topic/getInitialData/index.js index f074910326b..978ee7a1259 100644 --- a/src/app/routes/topic/getInitialData/index.js +++ b/src/app/routes/topic/getInitialData/index.js @@ -20,7 +20,7 @@ const overrideRendererEnv = pathname => { return pathname; }; -export default async ({ service, path: pathname, variant, page, getAgent }) => { +export default async ({ service, path: pathname, variant, page }) => { try { const { status, json } = await fetchDataFromBFF({ pathname: overrideRendererEnv(pathname), @@ -28,7 +28,6 @@ export default async ({ service, path: pathname, variant, page, getAgent }) => { variant, pageType: TOPIC_PAGE, page, - getAgent, }); const { data } = json; diff --git a/src/app/routes/topic/getInitialData/index.test.js b/src/app/routes/topic/getInitialData/index.test.js index b203dc448d6..d8ce73e9de2 100644 --- a/src/app/routes/topic/getInitialData/index.test.js +++ b/src/app/routes/topic/getInitialData/index.test.js @@ -49,9 +49,6 @@ const topicJSON = { const optHeaders = { 'ctx-service-env': 'live' }; const agent = { ca: 'ca', key: 'key' }; - -const mockGetAgent = () => Promise.resolve(agent); - jest.mock('../../../../server/utilities/getAgent', () => jest.fn(() => Promise.resolve(agent)), ); @@ -73,7 +70,6 @@ describe('get initial data for topic', () => { const { pageData } = await getInitialData({ path: 'pidgin/topics/c0000000000t', service: 'pidgin', - getAgent: mockGetAgent, }); const { curations } = pageData; expect(pageData.title).toEqual('Donald Trump'); @@ -104,7 +100,6 @@ describe('get initial data for topic', () => { const { pageData } = await getInitialData({ path: 'pidgin/topics/c0000000000t', service: 'pidgin', - getAgent: mockGetAgent, }); expect(pageData.title).toEqual('Donald Trump'); expect(pageData.imageData).toEqual(null); @@ -120,7 +115,6 @@ describe('get initial data for topic', () => { const { pageData } = await getInitialData({ path: 'pidgin/topics/c0000000000t', service: 'pidgin', - getAgent: mockGetAgent, }); expect(pageData.title).toEqual('Donald Trump'); expect(pageData.description).toEqual(''); @@ -132,7 +126,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -150,7 +143,6 @@ describe('get initial data for topic', () => { path: 'serbian/cyr/topics/c0000000000t', service: 'serbian', variant: 'cyr', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -167,7 +159,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t.amp', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -184,7 +175,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t?foo=bar', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -201,7 +191,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t.amp?foo=bar', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -219,7 +208,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -235,7 +223,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t?renderer_env=test', service: 'pidgin', - getAgent: mockGetAgent, }); const testHeader = { 'ctx-service-env': 'test' }; @@ -255,7 +242,6 @@ describe('get initial data for topic', () => { await getInitialData({ path: 'pidgin/topics/c0000000000t?renderer_env=live', service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -273,7 +259,6 @@ describe('get initial data for topic', () => { path: 'pidgin/topics/c0000000000t', service: 'pidgin', page: 20, - getAgent: mockGetAgent, }); expect(fetchDataSpy).toHaveBeenCalledWith({ @@ -292,7 +277,6 @@ describe('get initial data for topic', () => { path: 'pidgin/topics/c0000000000t', service: 'pidgin', page: 20, - getAgent: mockGetAgent, }), ).resolves.toHaveProperty('pageData.metadata', { type: 'Topic', diff --git a/src/app/routes/utils/certsRequired/index.ts b/src/app/routes/utils/certsRequired/index.ts index 6977407ace1..21028f05b80 100644 --- a/src/app/routes/utils/certsRequired/index.ts +++ b/src/app/routes/utils/certsRequired/index.ts @@ -3,10 +3,7 @@ import getEnvironment from '../getEnvironment'; export default (pathname: string) => { const environment = getEnvironment(pathname); const isLocal = environment === 'local' || !environment; - const BFF_IS_LOCAL = process?.env?.BFF_PATH?.includes('localhost:3210'); - return ( - !BFF_IS_LOCAL && !isLocal && process.env.LIGHTHOUSE_BUILD !== 'true' && process.env.CYPRESS_APP_ENV !== 'local' diff --git a/src/app/routes/utils/fetchDataFromBFF/index.test.ts b/src/app/routes/utils/fetchDataFromBFF/index.test.ts index bac8476af73..c9ecde273f6 100644 --- a/src/app/routes/utils/fetchDataFromBFF/index.test.ts +++ b/src/app/routes/utils/fetchDataFromBFF/index.test.ts @@ -1,4 +1,4 @@ -import { Agent } from 'undici'; +import { Agent } from 'http'; import fetchDataFromBFF from '.'; import { ARTICLE_PAGE, @@ -18,13 +18,11 @@ jest.mock('../fetchPageData', () => }), ); -const mockAgent = { - connect: { cert: 'cert', ca: 'ca', key: 'key' }, -} as unknown as Agent; +const mockAgent = { cert: 'cert', ca: 'ca', key: 'key' }; -const mockGetAgent = () => Promise.resolve(mockAgent); - -jest.mock('../../../../server/utilities/getAgent', () => jest.fn(mockGetAgent)); +jest.mock('../../../../server/utilities/getAgent', () => + jest.fn(() => Promise.resolve(mockAgent as unknown as Agent)), +); const localTimeout = 60000; @@ -59,7 +57,6 @@ describe('Fetch Data from BFF', () => { pathname, pageType: ARTICLE_PAGE, service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchPageDataSpy).toHaveBeenCalledWith({ @@ -97,7 +94,6 @@ describe('Fetch Data from BFF', () => { pathname, pageType: CPS_ASSET, service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchPageDataSpy).toHaveBeenCalledWith({ @@ -136,7 +132,6 @@ describe('Fetch Data from BFF', () => { pathname, pageType: TOPIC_PAGE, service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchPageDataSpy).toHaveBeenCalledWith({ @@ -174,7 +169,6 @@ describe('Fetch Data from BFF', () => { pathname, pageType: MOST_READ_PAGE, service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchPageDataSpy).toHaveBeenCalledWith({ @@ -212,7 +206,6 @@ describe('Fetch Data from BFF', () => { pathname, pageType: HOME_PAGE, service: 'pidgin', - getAgent: mockGetAgent, }); expect(fetchPageDataSpy).toHaveBeenCalledWith({ diff --git a/src/app/routes/utils/fetchDataFromBFF/index.ts b/src/app/routes/utils/fetchDataFromBFF/index.ts index 3af4b464129..13e1a415e2a 100644 --- a/src/app/routes/utils/fetchDataFromBFF/index.ts +++ b/src/app/routes/utils/fetchDataFromBFF/index.ts @@ -1,14 +1,17 @@ +import getAgent from '../../../../server/utilities/getAgent'; import constructPageFetchUrl from '../constructPageFetchUrl'; import getEnvironment from '../getEnvironment'; import { Services, Variants, PageTypes } from '../../../models/types/global'; import fetchPageData from '../fetchPageData'; import getErrorStatusCode from '../fetchPageData/utils/getErrorStatusCode'; import { BFF_FETCH_ERROR } from '../../../lib/logger.const'; -import { FetchError, GetAgent } from '../../../models/types/fetch'; +import { FetchError } from '../../../models/types/fetch'; import nodeLogger from '../../../lib/logger.node'; -import certsRequired from '../certsRequired'; const logger = nodeLogger(__filename); +const BFF_IS_LOCAL = + process.env.JEST_WORKER_ID === undefined && + process?.env?.BFF_PATH?.includes('localhost:3210'); interface FetchDataFromBffParams { pathname: string; @@ -17,9 +20,15 @@ interface FetchDataFromBffParams { variant?: Variants; isAmp?: boolean; page?: string; - getAgent?: GetAgent; } +type OptHeaders = + | { + 'ctx-service-env': string; + Accept?: string; + } + | undefined; + export default async ({ pathname, pageType, @@ -27,12 +36,9 @@ export default async ({ variant, isAmp, page, - getAgent, }: FetchDataFromBffParams) => { const environment = getEnvironment(pathname); - const isLocal = !environment || environment === 'local'; - const optHeaders = isLocal ? undefined : { 'ctx-service-env': environment }; const fetchUrl = constructPageFetchUrl({ pathname, @@ -43,20 +49,27 @@ export default async ({ page, }); - const useCerts = certsRequired(pathname); + const agent = isLocal || BFF_IS_LOCAL ? undefined : await getAgent(); + const timeout = isLocal || BFF_IS_LOCAL ? 60000 : null; - const agent = useCerts && getAgent ? await getAgent() : undefined; - const timeout = useCerts ? undefined : 60000; + const optHeaders: OptHeaders = isLocal + ? undefined + : { + 'ctx-service-env': environment, + }; + + if (BFF_IS_LOCAL && optHeaders) { + optHeaders.Accept = 'text/html,application/xhtml+xml,application/xml'; + } try { const fetchPageDataArgs = { path: fetchUrl.toString(), + agent, + optHeaders, pageType, - ...(agent && { agent }), - ...(optHeaders && { optHeaders }), ...(timeout && { timeout }), }; - // @ts-expect-error - Ignore fetchPageData argument types const { status, json } = await fetchPageData(fetchPageDataArgs); diff --git a/src/app/routes/utils/fetchPageData/index.js b/src/app/routes/utils/fetchPageData/index.js index b088d371fa1..4aabe06ca7b 100644 --- a/src/app/routes/utils/fetchPageData/index.js +++ b/src/app/routes/utils/fetchPageData/index.js @@ -1,3 +1,4 @@ +import 'isomorphic-fetch'; import nodeLogger from '#lib/logger.node'; import { DATA_FETCH_RESPONSE_TIME, @@ -20,7 +21,7 @@ import getUrl from './utils/getUrl'; const logger = nodeLogger(__filename); /** - * A fetch wrapper for pages, with error and log handling. + * An isomorphic fetch wrapper for pages, with error and log handling. * @param {string} path The URL of a resource to fetch. * @param {number} timeout Optional parameter to provide a custom timeout * for request for 'secondary data'. The fetch timeout defaults to the 'primary @@ -69,7 +70,7 @@ const fetchPageData = async ({ 'User-Agent': 'Simorgh/ws-web-rendering', ...(optHeaders && optHeaders), }, - signal: AbortSignal.timeout(effectiveTimeout), + timeout: effectiveTimeout, ...(agent && { agent }), }; diff --git a/src/app/routes/utils/fetchPageData/index.test.js b/src/app/routes/utils/fetchPageData/index.test.js index ba65ff4e480..1e64d4596b6 100644 --- a/src/app/routes/utils/fetchPageData/index.test.js +++ b/src/app/routes/utils/fetchPageData/index.test.js @@ -22,10 +22,7 @@ const requestOrigin = 'Jest Test'; jest.mock('#app/lib/utilities/isLocal', () => jest.fn()); -const timeoutSpy = jest.spyOn(AbortSignal, 'timeout'); - afterEach(() => { - timeoutSpy.mockClear(); jest.clearAllMocks(); fetch.resetMocks(); }); @@ -88,33 +85,30 @@ describe('fetchPageData', () => { headers: { 'User-Agent': 'Simorgh/ws-web-rendering', }, + timeout: 4000, }; it('should call fetch with the correct url when passed the pathname', async () => { await fetchPageData({ path: requestedPathname, pageType }); - expect(timeoutSpy).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(expectedUrl, fetchOptions); }); it('should call fetch with the correct url when passed the full test path', async () => { await fetchPageData({ path: fullTestPath, pageType }); - expect(timeoutSpy).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(fullTestPath, fetchOptions); }); it('should call fetch with the correct url when passed the full live path', async () => { await fetchPageData({ path: fullLivePath, pageType }); - expect(timeoutSpy).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(fullLivePath, fetchOptions); }); it('should call fetch on amp pages without .amp in pathname', async () => { await fetchPageData({ path: requestedPathname, pageType }); - expect(timeoutSpy).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(expectedUrl, fetchOptions); }); @@ -126,10 +120,10 @@ describe('fetchPageData', () => { 'User-Agent': 'Simorgh/ws-web-rendering', 'ctx-service-env': 'live', }, + timeout: 4000, }; await fetchPageData({ path: requestedPathname, pageType, optHeaders }); - expect(timeoutSpy).toHaveBeenCalledTimes(1); expect(fetch).toHaveBeenCalledWith(expectedUrl, expectedFetchOptions); }); diff --git a/src/app/routes/utils/withRadioSchedule/index.js b/src/app/routes/utils/withRadioSchedule/index.js index eb67cb9bc48..7bda2d54603 100644 --- a/src/app/routes/utils/withRadioSchedule/index.js +++ b/src/app/routes/utils/withRadioSchedule/index.js @@ -1,3 +1,4 @@ +import 'isomorphic-fetch'; import nodeLogger from '#lib/logger.node'; import { getRadioScheduleEndpoint } from '#lib/utilities/getUrlHelpers/getRadioSchedulesUrls'; import { getQueryString } from '#lib/utilities/urlParser'; diff --git a/src/integration/utils/fetchDom.js b/src/integration/utils/fetchDom.js index 6b831795058..de2906c3c54 100644 --- a/src/integration/utils/fetchDom.js +++ b/src/integration/utils/fetchDom.js @@ -1,5 +1,7 @@ /* eslint-disable no-console */ +const fetch = require('isomorphic-fetch'); + // https://github.com/node-fetch/node-fetch/issues/1624#issuecomment-1407717012 const dns = require('node:dns'); diff --git a/src/server/utilities/getAgent/certs.js b/src/server/utilities/getAgent/certs.js new file mode 100644 index 00000000000..835f4a4897e --- /dev/null +++ b/src/server/utilities/getAgent/certs.js @@ -0,0 +1,33 @@ +import { promises as fs } from 'fs'; + +const loadFiles = ({ caPath, certChainPath, keyPath }) => + Promise.all([ + fs.readFile(caPath, 'UTF-8'), + fs.readFile(certChainPath, 'UTF-8'), + fs.readFile(keyPath, 'UTF-8'), + ]); + +const getCert = async () => { + const caPath = process.env.CA_PATH || '/etc/pki/tls/certs/ca-bundle.crt'; + const certChainPath = + process.env.CERT_CHAIN_PATH || '/etc/pki/tls/certs/client.crt'; + const keyPath = process.env.KEY_PATH || '/etc/pki/tls/private/client.key'; + + try { + const [ca, certChain, key] = await loadFiles({ + caPath, + certChainPath, + keyPath, + }); + + if (!ca) throw new Error(`No valid CA Bundle found`); + if (!certChain) throw new Error(`No valid Public Key Chain found`); + if (!key) throw new Error(`No valid Private Key found`); + + return { ca, certChain, key }; + } catch (error) { + throw new Error(`Error loading certificate: ${error}`); + } +}; + +export default getCert; diff --git a/src/server/utilities/getAgent/index.js b/src/server/utilities/getAgent/index.js new file mode 100644 index 00000000000..d5e5ea899d2 --- /dev/null +++ b/src/server/utilities/getAgent/index.js @@ -0,0 +1,22 @@ +import { Agent } from 'https'; +import { createSecureContext } from 'tls'; +import getCert from './certs'; + +let agentMemo = null; + +const getAgent = async () => { + if (agentMemo) { + return agentMemo; + } + + const { certChain, key, ca } = await getCert(); + + agentMemo = new Agent({ + secureContext: createSecureContext({ cert: certChain, key, ca }), + keepAlive: true, + }); + + return agentMemo; +}; + +export default getAgent; diff --git a/src/server/utilities/getAgent/index.test.js b/src/server/utilities/getAgent/index.test.js new file mode 100644 index 00000000000..a24235100bf --- /dev/null +++ b/src/server/utilities/getAgent/index.test.js @@ -0,0 +1,44 @@ +import { Agent } from 'https'; +import getAgent from '.'; +import getCerts from './certs'; + +jest.mock('https', () => ({ + Agent: jest.fn(), +})); + +jest.mock('tls', () => ({ + createSecureContext: jest.fn().mockReturnValue({ + context: { + ca: 'someCa', + cert: 'someCert', + key: 'someKey', + }, + }), +})); + +jest.mock('./certs'); + +describe('Agent', () => { + it('should only call for the certificate once, then store in memo', async () => { + getCerts.mockReturnValue({ + ca: 'someCa', + certChain: 'someCert', + key: 'someKey', + }); + await getAgent(); + await getAgent(); + + expect(getCerts).toHaveBeenCalledTimes(1); + expect(Agent).toHaveBeenCalledTimes(1); + expect(Agent).toHaveBeenCalledWith({ + keepAlive: true, + secureContext: { + context: { + ca: 'someCa', + cert: 'someCert', + key: 'someKey', + }, + }, + }); + }); +}); diff --git a/src/testHelpers/jest-setup.js b/src/testHelpers/jest-setup.js index c56feb5d69f..ee458ad8b6f 100644 --- a/src/testHelpers/jest-setup.js +++ b/src/testHelpers/jest-setup.js @@ -1,7 +1,6 @@ import fetch from 'jest-fetch-mock'; import path from 'path'; import { TextEncoder, TextDecoder } from 'util'; -import { ReadableStream } from 'node:stream/web'; global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; @@ -30,10 +29,6 @@ window.matchMedia = jest.fn().mockImplementation(query => { window.require = jest.fn(); global.fetch = fetch; -global.AbortSignal = { - timeout: jest.fn(), -}; -global.ReadableStream = ReadableStream; process.env.SIMORGH_PUBLIC_STATIC_ASSETS_ORIGIN = 'http://localhost:7080'; process.env.SIMORGH_PUBLIC_STATIC_ASSETS_PATH = '/'; diff --git a/ws-nextjs-app/package.json b/ws-nextjs-app/package.json index bd15b188247..b77e1d87fb0 100644 --- a/ws-nextjs-app/package.json +++ b/ws-nextjs-app/package.json @@ -41,6 +41,7 @@ "ts-node": "^10.9.2" }, "dependencies": { - "next": "14.2.10" + "next": "14.2.10", + "undici": "6.20.1" } } diff --git a/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.test.ts b/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.test.ts index eea5af4d322..bf89561daff 100644 --- a/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.test.ts +++ b/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.test.ts @@ -4,7 +4,7 @@ import russianFixtureData from '#data/russian/av-embeds/features-49881797/pid/p0 import handleAvRoute from './handleAvRoute'; const agent = { cert: 'cert', ca: 'ca', key: 'key' }; -jest.mock('#server/utilities/getAgent', () => +jest.mock('../../../utilities/undiciAgent', () => jest.fn(() => Promise.resolve(agent)), ); diff --git a/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.ts b/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.ts index 3850703996f..715a8a0e63f 100644 --- a/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.ts +++ b/ws-nextjs-app/pages/[service]/av-embeds/handleAvRoute.ts @@ -13,7 +13,7 @@ import { OK } from '#app/lib/statusCodes.const'; import { BFF_FETCH_ERROR, ROUTING_INFORMATION } from '#app/lib/logger.const'; import sendCustomMetric from '#server/utilities/customMetrics'; import { NON_200_RESPONSE } from '#server/utilities/customMetrics/metrics.const'; -import getAgent from '#server/utilities/getAgent'; +import getAgent from '../../../utilities/undiciAgent'; const logger = nodeLogger(__filename); diff --git a/ws-nextjs-app/pages/[service]/live/[id]/[[...variant]].page.tsx b/ws-nextjs-app/pages/[service]/live/[id]/[[...variant]].page.tsx index 42e64a0bbc7..e41a3ae88b5 100644 --- a/ws-nextjs-app/pages/[service]/live/[id]/[[...variant]].page.tsx +++ b/ws-nextjs-app/pages/[service]/live/[id]/[[...variant]].page.tsx @@ -1,23 +1,95 @@ import { GetServerSideProps } from 'next'; +import constructPageFetchUrl from '#app/routes/utils/constructPageFetchUrl'; +import getToggles from '#app/lib/utilities/getToggles/withCache'; import { LIVE_PAGE } from '#app/routes/utils/pageTypes'; import nodeLogger from '#lib/logger.node'; import logResponseTime from '#server/utilities/logResponseTime'; import isAppPath from '#app/routes/utils/isAppPath'; -import { ROUTING_INFORMATION } from '#app/lib/logger.const'; +import { ROUTING_INFORMATION, BFF_FETCH_ERROR } from '#app/lib/logger.const'; +import { FetchError } from '#models/types/fetch'; + +import getEnvironment from '#app/routes/utils/getEnvironment'; +import fetchPageData from '#app/routes/utils/fetchPageData'; +import certsRequired from '#app/routes/utils/certsRequired'; import { OK } from '#app/lib/statusCodes.const'; import sendCustomMetric from '#server/utilities/customMetrics'; import { NON_200_RESPONSE } from '#server/utilities/customMetrics/metrics.const'; import isLitePath from '#app/routes/utils/isLitePath'; import PageDataParams from '#app/models/types/pageDataParams'; +import getAgent from '../../../../utilities/undiciAgent'; import LivePageLayout from './LivePageLayout'; import extractHeaders from '../../../../../src/server/utilities/extractHeaders'; import isValidPageNumber from '../../../../utilities/pageQueryValidator'; -import getPageData from '../../../../utilities/pageRequests/getPageData'; const logger = nodeLogger(__filename); +const getPageData = async ({ + id, + page, + service, + variant, + rendererEnv, + resolvedUrl, +}: PageDataParams) => { + const pathname = `${id}${rendererEnv ? `?renderer_env=${rendererEnv}` : ''}`; + const livePageUrl = constructPageFetchUrl({ + page, + pageType: 'live', + pathname, + service, + variant, + }); + const env = getEnvironment(pathname); + const optHeaders = { 'ctx-service-env': env }; + + const agent = certsRequired(pathname) ? await getAgent() : null; + + let pageStatus; + let pageJson; + let errorMessage; + + const path = livePageUrl.toString(); + + try { + // @ts-expect-error Due to jsdoc inference, and no TS within fetchPageData + const { status, json } = await fetchPageData({ + path, + agent, + optHeaders, + }); + pageStatus = status; + pageJson = json; + } catch (error: unknown) { + const { message, status } = error as FetchError; + + sendCustomMetric({ + metricName: NON_200_RESPONSE, + statusCode: status, + pageType: LIVE_PAGE, + requestUrl: resolvedUrl, + }); + + logger.error(BFF_FETCH_ERROR, { + service, + status, + pathname, + message, + }); + pageStatus = status; + errorMessage = message; + } + + const data = pageJson + ? { pageData: pageJson.data, status: pageStatus } + : { error: errorMessage, status: pageStatus }; + + const toggles = await getToggles(service); + + return { data, toggles }; +}; + export const getServerSideProps: GetServerSideProps = async context => { context.res.setHeader( 'Cache-Control', @@ -76,7 +148,6 @@ export const getServerSideProps: GetServerSideProps = async context => { variant, rendererEnv, resolvedUrl: context.resolvedUrl, - pageType: LIVE_PAGE, }); let routingInfoLogger = logger.debug; @@ -91,7 +162,6 @@ export const getServerSideProps: GetServerSideProps = async context => { }); context.res.statusCode = data.status; - return { props: { error: data?.error || null, diff --git a/ws-nextjs-app/pages/[service]/send/[id]/[[...variant]].page.tsx b/ws-nextjs-app/pages/[service]/send/[id]/[[...variant]].page.tsx index e816b37250e..f8283d8095b 100644 --- a/ws-nextjs-app/pages/[service]/send/[id]/[[...variant]].page.tsx +++ b/ws-nextjs-app/pages/[service]/send/[id]/[[...variant]].page.tsx @@ -1,4 +1,5 @@ import { GetServerSideProps } from 'next'; +import nodeLogger from '#lib/logger.node'; import PageDataParams from '#models/types/pageDataParams'; import { UGC_PAGE } from '#app/routes/utils/pageTypes'; import isLitePath from '#app/routes/utils/isLitePath'; @@ -7,6 +8,8 @@ import getPageData from '../../../../utilities/pageRequests/getPageData'; import UGCPageLayout from './UGCPageLayout'; import extractHeaders from '../../../../../src/server/utilities/extractHeaders'; +const logger = nodeLogger(__filename); + export const getServerSideProps: GetServerSideProps = async context => { context.res.setHeader( 'Cache-Control', @@ -24,14 +27,24 @@ export const getServerSideProps: GetServerSideProps = async context => { renderer_env: rendererEnv, } = context.query as PageDataParams; - const { data, toggles } = await getPageData({ + const fetchPageDataParams = { id, service, - variant, rendererEnv, resolvedUrl: context.resolvedUrl, + }; + + const constructUrlParams = { pageType: UGC_PAGE, - }); + service, + variant, + }; + + const { data, toggles } = await getPageData( + fetchPageDataParams, + constructUrlParams, + logger, + ); const { pageData = null, status } = data; diff --git a/ws-nextjs-app/utilities/pageRequests/getPageData.test.ts b/ws-nextjs-app/utilities/pageRequests/getPageData.test.ts index a619145a93e..475cfe6da72 100644 --- a/ws-nextjs-app/utilities/pageRequests/getPageData.test.ts +++ b/ws-nextjs-app/utilities/pageRequests/getPageData.test.ts @@ -1,11 +1,10 @@ +import loggerMock from '#testHelpers/loggerMock'; import * as fetchPageData from '#app/routes/utils/fetchPageData'; import * as getToggles from '#app/lib/utilities/getToggles'; import getPageData from './getPageData'; const agent = { cert: 'cert', ca: 'ca', key: 'key' }; -jest.mock('#server/utilities/getAgent', () => - jest.fn(() => Promise.resolve(agent)), -); +jest.mock('../undiciAgent', () => jest.fn(() => Promise.resolve(agent))); describe('getPageData', () => { beforeEach(() => { @@ -27,14 +26,20 @@ describe('getPageData', () => { jest.spyOn(getToggles, 'default').mockResolvedValue(toggleResponse); - const { data: actualData, toggles: actualToggles } = await getPageData({ - id: 'u50853489', - service: 'mundo', - variant: undefined, - rendererEnv: undefined, - resolvedUrl: '/mundo/send/u50853489', - pageType: 'ugcForm', - }); + const { data: actualData, toggles: actualToggles } = await getPageData( + { + id: 'u50853489', + service: 'mundo', + rendererEnv: undefined, + resolvedUrl: '/mundo/send/u50853489', + }, + { + pageType: 'ugcForm', + service: 'mundo', + variant: undefined, + }, + loggerMock, + ); expect(actualData).toStrictEqual({ pageData: fetchDataResponse, @@ -56,14 +61,20 @@ describe('getPageData', () => { jest.spyOn(getToggles, 'default').mockResolvedValue(toggleResponse); - const { data: actualData, toggles: actualToggles } = await getPageData({ - id: 'u50853489', - service: 'mundo', - variant: undefined, - rendererEnv: undefined, - resolvedUrl: '/mundo/send/u50853489', - pageType: 'ugcForm', - }); + const { data: actualData, toggles: actualToggles } = await getPageData( + { + id: 'u50853489', + service: 'mundo', + rendererEnv: undefined, + resolvedUrl: '/mundo/send/u50853489', + }, + { + pageType: 'ugcForm', + service: 'mundo', + variant: undefined, + }, + loggerMock, + ); expect(actualData).toStrictEqual({ error: errorMessage, diff --git a/ws-nextjs-app/utilities/pageRequests/getPageData.ts b/ws-nextjs-app/utilities/pageRequests/getPageData.ts index 1934d78beea..c27098a69d8 100644 --- a/ws-nextjs-app/utilities/pageRequests/getPageData.ts +++ b/ws-nextjs-app/utilities/pageRequests/getPageData.ts @@ -2,44 +2,53 @@ import { BFF_FETCH_ERROR } from '#app/lib/logger.const'; import getToggles from '#app/lib/utilities/getToggles'; import { FetchError } from '#app/models/types/fetch'; import PageDataParams from '#app/models/types/pageDataParams'; +import constructPageFetchUrl, { + UrlConstructParams, +} from '#app/routes/utils/constructPageFetchUrl'; import sendCustomMetric from '#server/utilities/customMetrics'; +import getEnvironment from '#app/routes/utils/getEnvironment'; import { NON_200_RESPONSE } from '#server/utilities/customMetrics/metrics.const'; -import getAgent from '#server/utilities/getAgent'; -import fetchDataFromBFF from '#app/routes/utils/fetchDataFromBFF'; -import nodeLogger from '#lib/logger.node'; - -const logger = nodeLogger(__filename); - -const getPageData = async ({ - id, - page, - service, - variant, - rendererEnv, - resolvedUrl, - pageType, -}: PageDataParams) => { +import fetchPageData from '#app/routes/utils/fetchPageData'; +import certsRequired from '#app/routes/utils/certsRequired'; +import getAgent from '../undiciAgent'; + +type LoggerType = { + error: (id: string, params: { [key: string]: string | number }) => void; +}; + +const getPageData = async ( + { id, service, rendererEnv, resolvedUrl }: PageDataParams, + constructUrlParams: Omit, + logger: LoggerType, +) => { const pathname = `${id}${rendererEnv ? `?renderer_env=${rendererEnv}` : ''}`; - let message; - let status; - let json; + + const env = getEnvironment(pathname); + const optHeaders = { 'ctx-service-env': env }; + const agent = certsRequired(pathname) ? await getAgent() : null; + + let pageStatus; + let pageJson; + let errorMessage; try { - ({ status, json } = await fetchDataFromBFF({ - pathname, - pageType, - service, - variant, - page, - getAgent, - })); + const pageUrl = constructPageFetchUrl({ ...constructUrlParams, pathname }); + const path = pageUrl.toString(); + // @ts-expect-error Due to jsdoc inference, and no TS within fetchPageData + const { status, json } = await fetchPageData({ + path, + agent, + optHeaders, + }); + pageStatus = status; + pageJson = json; } catch (error: unknown) { - ({ message, status } = error as FetchError); + const { message, status } = error as FetchError; sendCustomMetric({ metricName: NON_200_RESPONSE, statusCode: status, - pageType, + pageType: constructUrlParams.pageType, requestUrl: resolvedUrl, }); @@ -49,11 +58,13 @@ const getPageData = async ({ pathname, message, }); + pageStatus = status; + errorMessage = message; } - const data = json - ? { pageData: json.data, status } - : { error: message, status }; + const data = pageJson + ? { pageData: pageJson.data, status: pageStatus } + : { error: errorMessage, status: pageStatus }; const toggles = await getToggles(service); diff --git a/src/server/utilities/getAgent/certs.ts b/ws-nextjs-app/utilities/undiciAgent/certs.ts similarity index 100% rename from src/server/utilities/getAgent/certs.ts rename to ws-nextjs-app/utilities/undiciAgent/certs.ts diff --git a/src/server/utilities/getAgent/index.test.ts b/ws-nextjs-app/utilities/undiciAgent/index.test.ts similarity index 100% rename from src/server/utilities/getAgent/index.test.ts rename to ws-nextjs-app/utilities/undiciAgent/index.test.ts diff --git a/src/server/utilities/getAgent/index.ts b/ws-nextjs-app/utilities/undiciAgent/index.ts similarity index 89% rename from src/server/utilities/getAgent/index.ts rename to ws-nextjs-app/utilities/undiciAgent/index.ts index 7185869590e..cb0954055c4 100644 --- a/src/server/utilities/getAgent/index.ts +++ b/ws-nextjs-app/utilities/undiciAgent/index.ts @@ -23,7 +23,7 @@ const getAgent = async () => { }, }); - return setGlobalDispatcher(agentMemo) as unknown as Agent; + return setGlobalDispatcher(agentMemo); }; export default getAgent; diff --git a/yarn.lock b/yarn.lock index 0caf06c0a3a..c3dc2b12fba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5177,13 +5177,13 @@ __metadata: linkType: hard "@types/jsdom@npm:^21.0.0": - version: 21.1.6 - resolution: "@types/jsdom@npm:21.1.6" + version: 21.1.7 + resolution: "@types/jsdom@npm:21.1.7" dependencies: "@types/node": "npm:*" "@types/tough-cookie": "npm:*" parse5: "npm:^7.0.0" - checksum: 10/423fcaf3ec57ca45bcdebb15bd18cbcef1daa472fd00b15af125d0a7783f572d78a610ce23177ace66667548a9d97e306d7185a4930ad7a002e612c3491e6765 + checksum: 10/a5ee54aec813ac928ef783f69828213af4d81325f584e1fe7573a9ae139924c40768d1d5249237e62d51b9a34ed06bde059c86c6b0248d627457ec5e5d532dfa languageName: node linkType: hard @@ -5238,6 +5238,16 @@ __metadata: languageName: node linkType: hard +"@types/node-fetch@npm:^2.6.11": + version: 2.6.11 + resolution: "@types/node-fetch@npm:2.6.11" + dependencies: + "@types/node": "npm:*" + form-data: "npm:^4.0.0" + checksum: 10/c416df8f182ec3826278ea42557fda08f169a48a05e60722d9c8edd4e5b2076ae281c6b6601ad406035b7201f885b0257983b61c26b3f9eb0f41192a807b5de5 + languageName: node + linkType: hard + "@types/node-forge@npm:^1.3.0": version: 1.3.11 resolution: "@types/node-forge@npm:1.3.11" @@ -6856,7 +6866,7 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:~3.0.2": +"braces@npm:^3.0.3, braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -10899,8 +10909,8 @@ __metadata: linkType: hard "http-proxy-middleware@npm:^2.0.3": - version: 2.0.6 - resolution: "http-proxy-middleware@npm:2.0.6" + version: 2.0.7 + resolution: "http-proxy-middleware@npm:2.0.7" dependencies: "@types/http-proxy": "npm:^1.17.8" http-proxy: "npm:^1.18.1" @@ -10912,7 +10922,7 @@ __metadata: peerDependenciesMeta: "@types/express": optional: true - checksum: 10/768e7ae5a422bbf4b866b64105b4c2d1f468916b7b0e9c96750551c7732383069b411aa7753eb7b34eab113e4f77fb770122cb7fb9c8ec87d138d5ddaafda891 + checksum: 10/4a51bf612b752ad945701995c1c029e9501c97e7224c0cf3f8bf6d48d172d6a8f2b57c20fec469534fdcac3aa8a6f332224a33c6b0d7f387aa2cfff9b67216fd languageName: node linkType: hard @@ -11695,6 +11705,16 @@ __metadata: languageName: node linkType: hard +"isomorphic-fetch@npm:3.0.0": + version: 3.0.0 + resolution: "isomorphic-fetch@npm:3.0.0" + dependencies: + node-fetch: "npm:^2.6.1" + whatwg-fetch: "npm:^3.4.1" + checksum: 10/568fe0307528c63405c44dd3873b7b6c96c0d19ff795cb15846e728b6823bdbc68cc8c97ac23324509661316f12f551e43dac2929bc7030b8bc4d6aa1158b857 + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -11820,8 +11840,8 @@ __metadata: linkType: hard "jake@npm:^10.8.5": - version: 10.8.7 - resolution: "jake@npm:10.8.7" + version: 10.9.2 + resolution: "jake@npm:10.9.2" dependencies: async: "npm:^3.2.3" chalk: "npm:^4.0.2" @@ -11829,7 +11849,7 @@ __metadata: minimatch: "npm:^3.1.2" bin: jake: bin/cli.js - checksum: 10/ad1cfe398836df4e6962954e5095597c21c5af1ea5a4182f6adf0869df8aca467a2eeca7869bf44f47120f4dd4ea52589d16050d295c87a5906c0d744775acc3 + checksum: 10/3be324708f99f031e0aec49ef8fd872eb4583cbe8a29a0c875f554f6ac638ee4ea5aa759bb63723fd54f77ca6d7db851eaa78353301734ed3700db9cb109a0cd languageName: node linkType: hard @@ -13155,12 +13175,12 @@ __metadata: linkType: hard "micromatch@npm:^4.0.0, micromatch@npm:^4.0.2, micromatch@npm:^4.0.4": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" dependencies: - braces: "npm:^3.0.2" + braces: "npm:^3.0.3" picomatch: "npm:^2.3.1" - checksum: 10/a749888789fc15cac0e03273844dbd749f9f8e8d64e70c564bcf06a033129554c789bb9e30d7566d7ff6596611a08e58ac12cf2a05f6e3c9c47c50c4c7e12fa2 + checksum: 10/6bf2a01672e7965eb9941d1f02044fad2bd12486b5553dc1116ff24c09a8723157601dc992e74c911d896175918448762df3b3fd0a6b61037dd1a9766ddfbf58 languageName: node linkType: hard @@ -13658,7 +13678,21 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.12": +"node-fetch@npm:2.6.12": + version: 2.6.12 + resolution: "node-fetch@npm:2.6.12" + dependencies: + whatwg-url: "npm:^5.0.0" + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + checksum: 10/370ed4d906edad9709a81b54a0141d37d2973a27dc80c723d8ac14afcec6dc67bc6c70986a96992b64ec75d08159cc4b65ce6aa9063941168ea5ac73b24df9f8 + languageName: node + linkType: hard + +"node-fetch@npm:^2.6.1, node-fetch@npm:^2.6.12": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" dependencies: @@ -15921,6 +15955,7 @@ __metadata: next-test-api-route-handler: "npm:^4.0.8" npm-run-all2: "npm:6.2.2" ts-node: "npm:^10.9.2" + undici: "npm:6.20.1" languageName: unknown linkType: soft @@ -15988,6 +16023,7 @@ __metadata: "@types/js-cookie": "npm:^3.0.3" "@types/jsdom": "npm:^21.0.0" "@types/loadable__component": "npm:5.13.9" + "@types/node-fetch": "npm:^2.6.11" "@types/ramda": "npm:0.30.0" "@types/react": "npm:18.3.3" "@types/react-dom": "npm:18.3.1" @@ -16039,6 +16075,7 @@ __metadata: husky: "npm:9.1.4" inspectpack: "npm:4.7.1" intersection-observer: "npm:0.12.2" + isomorphic-fetch: "npm:3.0.0" jalaali-js: "npm:1.2.7" jest: "npm:29.7.0" jest-environment-jsdom: "npm:29.7.0" @@ -16055,6 +16092,7 @@ __metadata: moment: "npm:2.30.1" moment-timezone: "npm:0.5.45" morgan: "npm:1.10.0" + node-fetch: "npm:2.6.12" npm-run-all2: "npm:6.2.2" path-to-regexp: "npm:6.3.0" polyfill-crypto.getrandomvalues: "npm:1.0.0" @@ -16077,7 +16115,6 @@ __metadata: ts-jest: "npm:29.2.4" ts-loader: "npm:9.5.1" typescript: "npm:5.4.5" - undici: "npm:6.20.1" url-parse: "npm:1.5.10" uuid: "npm:8.3.2" wait-on: "npm:8.0.0" @@ -18077,6 +18114,13 @@ __metadata: languageName: node linkType: hard +"whatwg-fetch@npm:^3.4.1": + version: 3.6.20 + resolution: "whatwg-fetch@npm:3.6.20" + checksum: 10/2b4ed92acd6a7ad4f626a6cb18b14ec982bbcaf1093e6fe903b131a9c6decd14d7f9c9ca3532663c2759d1bdf01d004c77a0adfb2716a5105465c20755a8c57c + languageName: node + linkType: hard + "whatwg-mimetype@npm:^3.0.0": version: 3.0.0 resolution: "whatwg-mimetype@npm:3.0.0"