Skip to content

Commit addcc83

Browse files
use static URL for Oracle downloads
1 parent a1b1171 commit addcc83

File tree

3 files changed

+41
-25
lines changed

3 files changed

+41
-25
lines changed

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export const OPTION_TYPE_CHECKS: OptionTypeChecks = {
123123

124124
export const MIN_SUPPORTED_MYSQL = '5.7.19';
125125
export const MySQLCDNDownloadsBaseURL = 'https://cdn.mysql.com//Downloads/MySQL-'
126+
export const MySQLCDNArchivesBaseURL = 'https://cdn.mysql.com/archives/mysql-'
126127
// 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.
127128
export const DOWNLOADABLE_MYSQL_VERSIONS = [
128129
'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: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { randomUUID } from 'crypto';
88
import { execFile } from 'child_process';
99
import { BinaryInfo, InternalServerOptions } from '../../types';
1010
import { lockFile, waitForLock } from './FileLock';
11-
import { getInternalEnvVariable } from '../constants';
11+
import { getInternalEnvVariable, MySQLCDNArchivesBaseURL, MySQLCDNDownloadsBaseURL } from '../constants';
1212

1313
function handleTarExtraction(filepath: string, extractedPath: string): Promise<void> {
1414
return new Promise((resolve, reject) => {
@@ -25,12 +25,7 @@ function getFileDownloadURLRedirect(url: string): Promise<string> {
2525
const options: https.RequestOptions = {
2626
headers: {
2727
'accept': '*/*',
28-
'connection': 'keep-alive',
29-
"user-agent": 'mysql-memory-server-js-net/1.0.0',
30-
// Not too sure why, but the request fails without dummy headers
31-
// For the request to work, these headers have been added
32-
"hello": "hello",
33-
"world": "world"
28+
'connection': 'keep-alive'
3429
}
3530
}
3631

@@ -294,14 +289,16 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
294289
//The code below only runs if the lock has been acquired by us
295290

296291
let downloadTries = 0;
292+
let useDownloadsURL = false;
297293

298294
do {
295+
const downloadURL = binaryInfo.hostedByOracle ? `${useDownloadsURL ? MySQLCDNDownloadsBaseURL : MySQLCDNArchivesBaseURL}${url}` : await getFileDownloadURLRedirect(url)
299296
try {
300297
downloadTries++;
301-
logger.log(`Starting download for MySQL version ${version} from ${url}.`)
302-
await downloadFromCDN(url, archivePath, logger)
303-
logger.log(`Finished downloading MySQL version ${version} from ${url}. Now starting binary extraction.`)
304-
await extractBinary(url, archivePath, extractedPath, binaryInfo, logger)
298+
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`)
299+
await downloadFromCDN(downloadURL, archivePath, logger)
300+
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`)
301+
await extractBinary(downloadURL, archivePath, extractedPath, binaryInfo, logger)
305302
logger.log(`Finished extraction for version ${version}`)
306303
break
307304
} catch (e) {
@@ -315,14 +312,22 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
315312
logger.error('An error occurred while deleting extractedPath and/or archivePath:', e)
316313
}
317314

318-
if (e?.includes?.('status code 404')) {
319-
try {
320-
await releaseFunction()
321-
} catch (e) {
322-
logger.error('An error occurred while releasing lock after receiving a 404 error on download. The error was:', e)
315+
// If we got a 404 error while downloading a binary from Oracle and have not retried with the Downloads URL yet
316+
// then retry with the Downloads URL. Otherwise, reject.
317+
if (e?.includes('status code 404')) {
318+
if (binaryInfo.hostedByOracle && useDownloadsURL === false) {
319+
useDownloadsURL = true;
320+
downloadTries--
321+
continue
322+
} else {
323+
try {
324+
await releaseFunction()
325+
} catch (e) {
326+
logger.error('An error occurred while releasing lock after receiving a 404 error on download. The error was:', e)
327+
} finally {
328+
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404 at URL ${downloadURL}. Aborting download.`)
329+
}
323330
}
324-
325-
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404. Aborting download.`)
326331
}
327332

328333
if (downloadTries > options.downloadRetries) {
@@ -349,19 +354,21 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
349354
return resolve(binaryPath)
350355
} else {
351356
let downloadTries = 0;
357+
let useDownloadsURL = false;
352358

353359
do {
360+
const downloadURL = binaryInfo.hostedByOracle ? `${useDownloadsURL ? MySQLCDNDownloadsBaseURL : MySQLCDNArchivesBaseURL}${url}` : await getFileDownloadURLRedirect(url)
354361
const uuid = randomUUID()
355362
const zipFilepath = `${dirpath}/${uuid}.${fileExtension}`
356363
logger.log('Binary filepath:', zipFilepath)
357364
const extractedPath = `${dirpath}/${uuid}`
358365

359366
try {
360367
downloadTries++
361-
logger.log(`Starting download for MySQL version ${version} from ${url}.`)
362-
await downloadFromCDN(url, zipFilepath, logger)
363-
logger.log(`Finished downloading MySQL version ${version} from ${url}. Now starting binary extraction.`)
364-
const binaryPath = await extractBinary(url, zipFilepath, extractedPath, binaryInfo, logger)
368+
logger.log(`Starting download for MySQL version ${version} from ${downloadURL}.`)
369+
await downloadFromCDN(downloadURL, zipFilepath, logger)
370+
logger.log(`Finished downloading MySQL version ${version} from ${downloadURL}. Now starting binary extraction.`)
371+
const binaryPath = await extractBinary(downloadURL, zipFilepath, extractedPath, binaryInfo, logger)
365372
logger.log(`Finished extraction for version ${version}`)
366373
return resolve(binaryPath)
367374
} catch (e) {
@@ -375,8 +382,16 @@ export function downloadBinary(binaryInfo: BinaryInfo, options: InternalServerOp
375382
logger.error('An error occurred while deleting extractedPath and/or archivePath:', e)
376383
}
377384

378-
if (e?.includes?.('status code 404')) {
379-
return reject(`Binary download for MySQL version ${version} returned status code 404. Aborting download.`)
385+
// If we got a 404 error while downloading a binary from Oracle and have not retried with the Downloads URL yet
386+
// then retry with the Downloads URL. Otherwise, reject.
387+
if (e?.includes('status code 404')) {
388+
if (binaryInfo.hostedByOracle && useDownloadsURL === false) {
389+
useDownloadsURL = true;
390+
downloadTries--
391+
continue
392+
} else {
393+
return reject(`Binary download for MySQL version ${binaryInfo.version} returned status code 404 at URL ${downloadURL}. Aborting download.`)
394+
}
380395
}
381396

382397
if (downloadTries > options.downloadRetries) {

src/libraries/Version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export default function getBinaryURL(versionToGet: string = "x", currentArch: st
123123

124124
return {
125125
version: selectedVersion,
126-
url: isOnAlpineLinux ? fileLocation : (MySQLCDNDownloadsBaseURL + fileLocation),
126+
url: fileLocation,
127127
hostedByOracle: !isOnAlpineLinux, // Only the Alpine Linux binaries are not hosted on the MySQL CDN.
128128
xPluginSupported
129129
}

0 commit comments

Comments
 (0)