Skip to content

Commit 205b948

Browse files
update Downloader to expect status code 302
1 parent ddabae5 commit 205b948

File tree

2 files changed

+112
-29
lines changed

2 files changed

+112
-29
lines changed

src/constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ export const OPTION_TYPE_CHECKS: OptionTypeChecks = {
115115
} as const;
116116

117117
export const MIN_SUPPORTED_MYSQL = '5.7.19';
118-
export const downloadsBaseURL = 'https://cdn.mysql.com//Downloads/MySQL-'
119-
export const archiveBaseURL = 'https://cdn.mysql.com/archives/mysql-'
118+
export const downloadsBaseURL = 'https://dev.mysql.com/get/Downloads/MySQL-'
119+
export const archiveBaseURL = 'https://downloads.mysql.com/archives/get/p/23/file/mysql-'
120120
// Versions 8.0.29, 8.0.38, 8.4.1, and 9.0.0 have been purposefully left out of this list as MySQL has removed them from the CDN due to critical issues.
121121
export const DOWNLOADABLE_MYSQL_VERSIONS = [
122122
'5.7.19', '5.7.20', '5.7.21', '5.7.22', '5.7.23', '5.7.24', '5.7.25', '5.7.26', '5.7.27', '5.7.28', '5.7.29', '5.7.30', '5.7.31', '5.7.32', '5.7.33', '5.7.34', '5.7.35', '5.7.36', '5.7.37', '5.7.38', '5.7.39', '5.7.40', '5.7.41', '5.7.42', '5.7.43', '5.7.44',

src/libraries/Downloader.ts

Lines changed: 110 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,34 @@ function handleTarExtraction(filepath: string, extractedPath: string): Promise<v
2121
})
2222
}
2323

24+
function getFileDownloadURLRedirect(url: string): Promise<string> {
25+
return new Promise((resolve, reject) => {
26+
const request = https.get(url, response => {
27+
const statusCode = response.statusCode
28+
const location = response.headers.location
29+
30+
if (statusCode !== 302) {
31+
request.destroy();
32+
33+
reject(`Received status code ${statusCode} while getting redirect URL for binary download.`)
34+
return
35+
}
36+
37+
if (typeof location === 'string' && location.length > 0) {
38+
resolve(location)
39+
return
40+
}
41+
42+
reject(`Received incorrect URL information. Expected a non-empty string. Received: ${JSON.stringify(location)}`)
43+
})
44+
45+
request.on('error', (err) => {
46+
request.destroy();
47+
reject(err.message)
48+
})
49+
})
50+
}
51+
2452
function downloadFromCDN(url: string, downloadLocation: string, logger: Logger): Promise<void> {
2553
return new Promise(async (resolve, reject) => {
2654
if (fs.existsSync(downloadLocation)) {
@@ -245,13 +273,58 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
245273

246274
//The code below only runs if the lock has been acquired by us
247275

276+
let retryURL = false;
277+
let downloadURL = '';
278+
279+
if (hostedByOracle) {
280+
do {
281+
try {
282+
downloadURL = await getFileDownloadURLRedirect(retryURL ? url.replace(archiveBaseURL, downloadsBaseURL) : url)
283+
} catch (error) {
284+
if (retryURL) {
285+
try {
286+
await releaseFunction()
287+
} catch (e) {
288+
logger.error('An error occurred while releasing lock after receiving an error on both downloads and archives URLs. The error was:', error)
289+
}
290+
291+
return reject(`Both URLs for MySQL version ${binaryInfo.version} failed to give status code 302. Aborting download. Error: ${error}`)
292+
}
293+
294+
if (error?.includes?.('status code 404')) {
295+
retryURL = true;
296+
logger.log('Retrying with downloads URL as received status code 404')
297+
continue
298+
}
299+
300+
try {
301+
await releaseFunction()
302+
} catch (e) {
303+
logger.error('An error occurred while releasing lock after not received status code 302 or 404 for hostedByOracle binary. The error was:', error)
304+
}
305+
306+
return reject(`Did not receive status code 302 or 404 for MySQL binary download URL. The error was: ${error}`)
307+
}
308+
} while (retryURL)
309+
} else {
310+
try {
311+
downloadURL = await getFileDownloadURLRedirect(url)
312+
} catch (error) {
313+
try {
314+
await releaseFunction()
315+
} catch (e) {
316+
logger.error('An error occurred while releasing lock after not getting URL redirect for bimary download from GitHub. The error was:', e)
317+
}
318+
319+
return reject(`Did not get URL redirect for binary download from GitHub. The error was: ${error}`)
320+
}
321+
}
322+
248323
let downloadTries = 0;
249-
let useDownloadsURL = false;
250324

251325
do {
252326
try {
253327
downloadTries++;
254-
const downloadURL = useDownloadsURL ? url.replace(archiveBaseURL, downloadsBaseURL) : url
255328
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`)
256329
await downloadFromCDN(downloadURL, archivePath, logger)
257330
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`)
@@ -270,21 +343,13 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
270343
}
271344

272345
if (e?.includes?.('status code 404')) {
273-
if (!useDownloadsURL && hostedByOracle) {
274-
//Retry with downloads URL
275-
downloadTries--;
276-
useDownloadsURL = true;
277-
logger.log(`Encountered error 404 when using archives URL for version ${version}. Now retrying with the downloads URL.`)
278-
continue;
279-
} else {
280-
try {
281-
await releaseFunction()
282-
} catch (e) {
283-
logger.error('An error occurred while releasing lock after receiving a 404 error on both downloads and archives URLs. The error was:', e)
284-
}
285-
286-
return reject(`Both URLs for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`)
346+
try {
347+
await releaseFunction()
348+
} catch (e) {
349+
logger.error('An error occurred while releasing lock after receiving a 404 error on download. The error was:', e)
287350
}
351+
352+
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`)
288353
}
289354

290355
if (downloadTries > options.downloadRetries) {
@@ -311,7 +376,34 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
311376
return resolve(binaryPath)
312377
} else {
313378
let downloadTries = 0;
314-
let useDownloadsURL = false;
379+
let retryURL = false;
380+
let downloadURL = '';
381+
382+
if (hostedByOracle) {
383+
do {
384+
try {
385+
downloadURL = await getFileDownloadURLRedirect(retryURL ? url.replace(archiveBaseURL, downloadsBaseURL) : url)
386+
} catch (error) {
387+
if (retryURL) {
388+
return reject(`Both URLs for MySQL version ${binaryInfo.version} failed to give status code 302. Aborting download. Error: ${error}`)
389+
}
390+
391+
if (error?.includes?.('status code 404')) {
392+
retryURL = true;
393+
logger.log('Retrying with downloads URL as received status code 404')
394+
continue
395+
}
396+
397+
return reject(`Did not receive status code 302 or 404 for MySQL binary download URL. The error was: ${error}`)
398+
}
399+
} while (retryURL)
400+
} else {
401+
try {
402+
downloadURL = await getFileDownloadURLRedirect(url)
403+
} catch (error) {
404+
return reject(`Did not get URL redirect for binary download from GitHub. The error was: ${error}`)
405+
}
406+
}
315407

316408
do {
317409
const uuid = randomUUID()
@@ -321,7 +413,6 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
321413

322414
try {
323415
downloadTries++
324-
const downloadURL = useDownloadsURL ? url.replace(archiveBaseURL, downloadsBaseURL) : url
325416
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`)
326417
await downloadFromCDN(downloadURL, zipFilepath, logger)
327418
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`)
@@ -340,15 +431,7 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
340431
}
341432

342433
if (e?.includes?.('status code 404')) {
343-
if (!useDownloadsURL && hostedByOracle) {
344-
//Retry with downloads URL
345-
downloadTries--;
346-
useDownloadsURL = true;
347-
logger.log(`Encountered error 404 when using archives URL for version ${version}. Now retrying with the downloads URL.`)
348-
continue;
349-
} else {
350-
return reject(`Both URLs for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`)
351-
}
434+
return reject(`Binary download for MySQL version ${version} returned status code 404. Aborting download.`)
352435
}
353436

354437
if (downloadTries > options.downloadRetries) {

0 commit comments

Comments
 (0)