@@ -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+
2452function 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