Skip to content

Commit 6ff5188

Browse files
authored
[FIX]: reuse axios connections (#3625)
* fix: reuse connections for gamesdb queries * fix: tests * fix: use one axios session for all backend requests * fix: lint * fix: tests
1 parent 394ecee commit 6ff5188

File tree

22 files changed

+120
-105
lines changed

22 files changed

+120
-105
lines changed

src/backend/__tests__/utils.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import axios from 'axios'
1+
import { axiosClient } from 'backend/utils'
22
import { app } from 'electron'
33
import { logError } from '../logger/logger'
44
import * as utils from '../utils'
@@ -61,7 +61,7 @@ describe('backend/utils.ts', () => {
6161

6262
describe('getLatestReleases', () => {
6363
test('Simple version', async () => {
64-
jest.spyOn(axios, 'get').mockResolvedValue(test_data)
64+
jest.spyOn(axiosClient, 'get').mockResolvedValue(test_data)
6565
jest.spyOn(app, 'getVersion').mockReturnValueOnce('2.4.0')
6666

6767
const releases = await utils.getLatestReleases()
@@ -92,7 +92,7 @@ describe('backend/utils.ts', () => {
9292
})
9393

9494
test('Complex version', async () => {
95-
jest.spyOn(axios, 'get').mockResolvedValue(test_data)
95+
jest.spyOn(axiosClient, 'get').mockResolvedValue(test_data)
9696
jest.spyOn(app, 'getVersion').mockReturnValueOnce('2.5.5-beta.3')
9797

9898
const releases = await utils.getLatestReleases()
@@ -113,15 +113,15 @@ describe('backend/utils.ts', () => {
113113
})
114114

115115
test('Empty version', async () => {
116-
jest.spyOn(axios, 'get').mockResolvedValue(test_data)
116+
jest.spyOn(axiosClient, 'get').mockResolvedValue(test_data)
117117
jest.spyOn(app, 'getVersion').mockReturnValueOnce('')
118118

119119
const releases = await utils.getLatestReleases()
120120
expect(releases).toMatchInlineSnapshot(`[]`)
121121
})
122122

123123
test('Fetching available releases fails', async () => {
124-
jest.spyOn(axios, 'get').mockRejectedValue('Failed to fetch!')
124+
jest.spyOn(axiosClient, 'get').mockRejectedValue('Failed to fetch!')
125125

126126
const releases = await utils.getLatestReleases()
127127
expect(logError).toBeCalledWith(

src/backend/anticheat/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { anticheatDataPath, isMac, isWindows } from '../constants'
2-
import * as axios from 'axios'
32
import { logInfo, LogPrefix, logWarning } from '../logger/logger'
43
import { readFileSync, writeFileSync } from 'graceful-fs'
54
import { AntiCheatInfo } from 'common/types'
65
import { runOnceWhenOnline } from '../online_monitor'
6+
import { axiosClient } from 'backend/utils'
77

88
async function downloadAntiCheatData() {
99
if (isWindows) return
@@ -14,7 +14,7 @@ async function downloadAntiCheatData() {
1414
: 'https://raw.githubusercontent.com/Starz0r/AreWeAntiCheatYet/HEAD/games.json'
1515

1616
try {
17-
const { data } = await axios.default.get(url)
17+
const { data } = await axiosClient.get(url)
1818
writeFileSync(anticheatDataPath, JSON.stringify(data, null, 2))
1919
logInfo(`AreWeAntiCheatYet data downloaded`, LogPrefix.Backend)
2020
} catch (error) {

src/backend/storeManagers/gog/library.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
LogPrefix,
3737
logWarning
3838
} from '../../logger/logger'
39-
import { getGOGdlBin, getFileSize } from '../../utils'
39+
import { getGOGdlBin, getFileSize, axiosClient } from '../../utils'
4040
import { gogdlConfigPath, gogdlLogFile } from '../../constants'
4141
import {
4242
libraryStore,
@@ -118,7 +118,9 @@ async function createMissingGogdlManifest(
118118
// Get meta
119119
const url = currentBuild.urls[0]
120120

121-
const response = await axios.get(url.url, { responseType: 'arraybuffer' })
121+
const response = await axiosClient.get(url.url, {
122+
responseType: 'arraybuffer'
123+
})
122124
let manifestDataRaw = response.data.toString()
123125
if (currentBuild.generation === 2) {
124126
manifestDataRaw = unzipSync(response.data)
@@ -186,7 +188,7 @@ export async function getSaveSyncLocation(
186188
let response: GOGClientsResponse | undefined
187189
try {
188190
response = (
189-
await axios.get(
191+
await axiosClient.get(
190192
`https://remote-config.gog.com/components/galaxy_client/clients/${clientId}?component_version=2.0.45`
191193
)
192194
).data
@@ -856,7 +858,7 @@ export async function getBuilds(
856858
headers.Authorization = `Bearer ${access_token}`
857859
}
858860

859-
return axios.get(url.toString(), { headers })
861+
return axiosClient.get(url.toString(), { headers })
860862
}
861863

862864
export async function getMetaResponse(
@@ -878,7 +880,7 @@ export async function getMetaResponse(
878880

879881
for (const metaUrl of metaUrls) {
880882
try {
881-
const metaResponse = await axios.get(metaUrl.url, {
883+
const metaResponse = await axiosClient.get(metaUrl.url, {
882884
headers,
883885
validateStatus: (status) => status === 200 || status === 304
884886
})
@@ -995,9 +997,11 @@ export async function getGamesData(appName: string, lang?: string) {
995997
lang || 'en-US'
996998
}`
997999

998-
const response: AxiosResponse | null = await axios.get(url).catch(() => {
999-
return null
1000-
})
1000+
const response: AxiosResponse | null = await axiosClient
1001+
.get(url)
1002+
.catch(() => {
1003+
return null
1004+
})
10011005
if (!response) {
10021006
return null
10031007
}
@@ -1179,15 +1183,16 @@ export function getExecutable(appName: string): string {
11791183
* @param game_id ID of a game
11801184
* @param forceUpdate (optional) force data update check
11811185
* @param certificate (optional) Galaxy library certificate
1182-
* @param access_token (optional) GOG Galaxy access token
1186+
* @param accessToken (optional) GOG Galaxy access token
1187+
* multiple entries)
11831188
* @returns object {isUpdated, data}, where isUpdated is true when Etags match
11841189
*/
11851190
export async function getGamesdbData(
11861191
store: string,
11871192
game_id: string,
11881193
forceUpdate?: boolean,
11891194
certificate?: string,
1190-
access_token?: string
1195+
accessToken?: string
11911196
): Promise<{ isUpdated: boolean; data?: GamesDBData | undefined }> {
11921197
const pieceId = `${store}_${game_id}`
11931198
const cachedData = !forceUpdate ? apiInfoCache.get(pieceId) : null
@@ -1198,10 +1203,10 @@ export async function getGamesdbData(
11981203
const headers = {
11991204
...(cachedData?.etag ? { 'If-None-Match': cachedData.etag } : {}),
12001205
...(certificate ? { 'X-GOG-Library-Cert': certificate } : {}),
1201-
...(access_token ? { Authorization: `Bearer ${access_token}` } : {})
1206+
...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {})
12021207
}
12031208

1204-
const response = await axios
1209+
const response = await axiosClient
12051210
.get<GamesDBData>(url, { headers: headers })
12061211
.catch((error: AxiosError) => {
12071212
logError(
@@ -1241,7 +1246,7 @@ export async function getGamesdbData(
12411246
export async function getProductApi(
12421247
appName: string,
12431248
expand?: string[],
1244-
access_token?: string
1249+
accessToken?: string
12451250
): Promise<AxiosResponse<ProductsEndpointData> | null> {
12461251
expand = expand ?? []
12471252
const language = i18next.language
@@ -1252,12 +1257,12 @@ export async function getProductApi(
12521257
}
12531258

12541259
const headers: AxiosRequestHeaders = {}
1255-
if (access_token) {
1256-
headers.Authorization = `Bearer ${access_token}`
1260+
if (accessToken) {
1261+
headers.Authorization = `Bearer ${accessToken}`
12571262
}
12581263

12591264
// `https://api.gog.com/products/${appName}?locale=${language}${expandString}`
1260-
const response = await axios
1265+
const response = await axiosClient
12611266
.get<ProductsEndpointData>(url.toString(), { headers })
12621267
.catch(() => null)
12631268

src/backend/storeManagers/gog/redist.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import {
2323
getQueueInformation
2424
} from 'backend/downloadmanager/downloadqueue'
2525
import { DMQueueElement } from 'common/types'
26-
import axios from 'axios'
2726
import { GOGUser } from './user'
2827
import { isOnline } from 'backend/online_monitor'
28+
import { axiosClient } from 'backend/utils'
2929

3030
export async function checkForRedistUpdates() {
3131
if (!GOGUser.isLoggedIn() || !isOnline()) {
@@ -73,7 +73,7 @@ export async function checkForRedistUpdates() {
7373
// Check if manifest itself changed
7474
if (!shouldUpdate) {
7575
const buildId = manifest?.build_id
76-
const response = await axios.get(
76+
const response = await axiosClient.get(
7777
'https://content-system.gog.com/dependencies/repository?generation=2'
7878
)
7979
const newBuildId = response.data.build_id

src/backend/storeManagers/legendary/library.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ import {
2222
formatEpicStoreUrl,
2323
getLegendaryBin,
2424
isEpicServiceOffline,
25-
getFileSize
25+
getFileSize,
26+
axiosClient
2627
} from '../../utils'
2728
import {
2829
fallBackImage,
@@ -49,7 +50,6 @@ import { callRunner } from '../../launcher'
4950
import { dirname, join } from 'path'
5051
import { isOnline } from 'backend/online_monitor'
5152
import { update } from './games'
52-
import axios from 'axios'
5353
import { app } from 'electron'
5454
import { copySync } from 'fs-extra'
5555
import { LegendaryCommand } from './commands'
@@ -697,7 +697,7 @@ export async function getGameOverride(): Promise<GameOverride> {
697697
}
698698

699699
try {
700-
const response = await axios.get<ResponseDataLegendaryAPI>(
700+
const response = await axiosClient.get<ResponseDataLegendaryAPI>(
701701
'https://heroic.legendary.gl/v1/version.json'
702702
)
703703

@@ -716,7 +716,7 @@ export async function getGameSdl(
716716
appName: string
717717
): Promise<SelectiveDownload[]> {
718718
try {
719-
const response = await axios.get<Record<string, SelectiveDownload>>(
719+
const response = await axiosClient.get<Record<string, SelectiveDownload>>(
720720
`https://heroic.legendary.gl/v1/sdl/${appName}.json`
721721
)
722722

src/backend/tools/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { ExecResult, GameSettings, Runner, WineCommandArgs } from 'common/types'
2-
import axios from 'axios'
32

43
import {
54
existsSync,
@@ -15,6 +14,7 @@ import {
1514

1615
import { spawn } from 'child_process'
1716
import {
17+
axiosClient,
1818
downloadFile,
1919
execAsync,
2020
extractFiles,
@@ -67,7 +67,7 @@ async function installOrUpdateTool(tool: Tool) {
6767

6868
const {
6969
data: { assets }
70-
} = await axios.get(tool.url)
70+
} = await axiosClient.get(tool.url)
7171

7272
const { name, browser_download_url: downloadUrl } = assets[0]
7373
const latestVersion = name.replace('.tar.gz', '').replace('.tar.xz', '')

src/backend/utils.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
GameStatus
1313
} from 'common/types'
1414
import axios from 'axios'
15+
import https from 'node:https'
1516
import { app, dialog, shell, Notification, BrowserWindow } from 'electron'
1617
import {
1718
exec,
@@ -189,7 +190,7 @@ async function isEpicServiceOffline(
189190
})
190191

191192
try {
192-
const { data } = await axios.get(epicStatusApi)
193+
const { data } = await axiosClient.get(epicStatusApi)
193194

194195
for (const component of data.components) {
195196
const { name: name, status: indicator } = component
@@ -684,7 +685,7 @@ const getLatestReleases = async (): Promise<Release[]> => {
684685
logInfo('Checking for new Heroic Updates', LogPrefix.Backend)
685686

686687
try {
687-
const { data: releases } = await axios.get(GITHUB_API)
688+
const { data: releases } = await axiosClient.get(GITHUB_API)
688689
const latestStable: Release = releases.filter(
689690
(rel: Release) => rel.prerelease === false
690691
)[0]
@@ -730,7 +731,9 @@ const getCurrentChangelog = async (): Promise<Release | null> => {
730731
try {
731732
const current = app.getVersion()
732733

733-
const { data: release } = await axios.get(`${GITHUB_API}/tags/v${current}`)
734+
const { data: release } = await axiosClient.get(
735+
`${GITHUB_API}/tags/v${current}`
736+
)
734737

735738
return release as Release
736739
} catch (error) {
@@ -1261,7 +1264,7 @@ export async function downloadFile({
12611264

12621265
const connections = 5
12631266
try {
1264-
const response = await axios.head(url)
1267+
const response = await axiosClient.head(url)
12651268
fileSize = parseInt(response.headers['content-length'], 10)
12661269
} catch (err) {
12671270
logError(
@@ -1462,6 +1465,11 @@ async function extractDecompress(
14621465
}
14631466
}
14641467

1468+
const axiosClient = axios.create({
1469+
timeout: 10 * 1000,
1470+
httpsAgent: new https.Agent({ keepAlive: true })
1471+
})
1472+
14651473
export {
14661474
errorHandler,
14671475
execAsync,
@@ -1496,7 +1504,8 @@ export {
14961504
sendGameStatusUpdate,
14971505
sendProgressUpdate,
14981506
calculateEta,
1499-
extractFiles
1507+
extractFiles,
1508+
axiosClient
15001509
}
15011510

15021511
// Exported only for testing purpose

src/backend/wiki_game_info/applegamingwiki/__tests__/utils.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { logError } from 'backend/logger/logger'
22
import { getInfoFromAppleGamingWiki } from '../utils'
3-
import axios from 'axios'
3+
import { axiosClient } from 'backend/utils'
44
import { AppleGamingWikiInfo } from 'common/types'
55

66
jest.mock('backend/logger/logfile')
@@ -9,7 +9,7 @@ jest.mock('electron-store')
99

1010
describe('getInfoFromAppleGamingWiki', () => {
1111
test('fetches successfully', async () => {
12-
const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({
12+
const mockAxios = jest.spyOn(axiosClient, 'get').mockResolvedValueOnce({
1313
data: { query: { search: [{ pageid: 1 }] } }
1414
})
1515
mockAxios.mockResolvedValueOnce({
@@ -31,7 +31,7 @@ describe('getInfoFromAppleGamingWiki', () => {
3131
})
3232

3333
test('does not find page id', async () => {
34-
jest.spyOn(axios, 'get').mockResolvedValueOnce({
34+
jest.spyOn(axiosClient, 'get').mockResolvedValueOnce({
3535
data: { query: { search: [{ pageid: undefined }] } }
3636
})
3737

@@ -40,7 +40,7 @@ describe('getInfoFromAppleGamingWiki', () => {
4040
})
4141

4242
test('does not find wikitext', async () => {
43-
const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({
43+
const mockAxios = jest.spyOn(axiosClient, 'get').mockResolvedValueOnce({
4444
data: { query: { search: [{ pageid: 1 }] } }
4545
})
4646
mockAxios.mockResolvedValueOnce({
@@ -60,7 +60,7 @@ describe('getInfoFromAppleGamingWiki', () => {
6060
})
6161

6262
test('wikitext empty', async () => {
63-
const mockAxios = jest.spyOn(axios, 'get').mockResolvedValueOnce({
63+
const mockAxios = jest.spyOn(axiosClient, 'get').mockResolvedValueOnce({
6464
data: { query: { search: [{ pageid: 1 }] } }
6565
})
6666
mockAxios.mockResolvedValueOnce({
@@ -80,7 +80,7 @@ describe('getInfoFromAppleGamingWiki', () => {
8080
})
8181

8282
test('catches axios throws', async () => {
83-
jest.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Failed'))
83+
jest.spyOn(axiosClient, 'get').mockRejectedValueOnce(new Error('Failed'))
8484

8585
const result = await getInfoFromAppleGamingWiki('The Witcher 3')
8686
expect(result).toBeNull()

0 commit comments

Comments
 (0)