mirror of
https://github.com/SKCraft/Launcher.git
synced 2024-11-30 13:13:58 +01:00
Fix bad logic surrounding download resuming
An oversight in the implementation of partial download resumption led to cross-contamination in the presence of multiple request URLs, where an `Accept-Ranges` header from one server would cause a `Range` header to be supplied to the next. Compounded with a bad ternary expression in `HttpRequest` which couldn't handle non-200 success codes, this was causing cryptic "Stream closed" errors on library downloads.
This commit is contained in:
parent
f7bbe82dfb
commit
f23d387609
@ -238,7 +238,6 @@ public class HttpDownloader implements Downloader {
|
|||||||
int trial = 0;
|
int trial = 0;
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
IOException lastException = null;
|
IOException lastException = null;
|
||||||
HttpRequest.PartialDownloadInfo retryDetails = null;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (URL url : urls) {
|
for (URL url : urls) {
|
||||||
@ -249,17 +248,10 @@ public class HttpDownloader implements Downloader {
|
|||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
request = HttpRequest.get(url);
|
tryDownloadFrom(url, file, null, 0);
|
||||||
request.setResumeInfo(retryDetails).execute().expectResponseCode(200).saveContent(file);
|
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
lastException = e;
|
lastException = e;
|
||||||
log.log(Level.WARNING, "Failed to download " + url, e);
|
|
||||||
|
|
||||||
Optional<HttpRequest.PartialDownloadInfo> byteRangeSupport = request.canRetryPartial();
|
|
||||||
if (byteRangeSupport.isPresent()) {
|
|
||||||
retryDetails = byteRangeSupport.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (++trial < tryCount);
|
} while (++trial < tryCount);
|
||||||
@ -267,6 +259,27 @@ public class HttpDownloader implements Downloader {
|
|||||||
throw new IOException("Failed to download from " + urls, lastException);
|
throw new IOException("Failed to download from " + urls, lastException);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryDownloadFrom(URL url, File file, HttpRequest.PartialDownloadInfo retryDetails, int tries)
|
||||||
|
throws InterruptedException, IOException {
|
||||||
|
try {
|
||||||
|
request = HttpRequest.get(url);
|
||||||
|
request.setResumeInfo(retryDetails).execute().expectResponseCode(200).saveContent(file);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.log(Level.WARNING, "Failed to download " + url, e);
|
||||||
|
|
||||||
|
// We only want to try to resume a partial download if the request succeeded before
|
||||||
|
// throwing an exception halfway through. If it didn't succeed, just throw the error.
|
||||||
|
if (tries >= tryCount || !request.isSuccessCode()) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<HttpRequest.PartialDownloadInfo> byteRangeSupport = request.canRetryPartial();
|
||||||
|
if (byteRangeSupport.isPresent()) {
|
||||||
|
tryDownloadFrom(url, file, byteRangeSupport.get(), tries + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getProgress() {
|
public double getProgress() {
|
||||||
HttpRequest request = this.request;
|
HttpRequest request = this.request;
|
||||||
|
@ -117,8 +117,7 @@ public class HttpRequest implements Closeable, ProgressObservable {
|
|||||||
|
|
||||||
conn = this.runRequest(url);
|
conn = this.runRequest(url);
|
||||||
|
|
||||||
inputStream = conn.getResponseCode() == HttpURLConnection.HTTP_OK ?
|
inputStream = isSuccessCode() ? conn.getInputStream() : conn.getErrorStream();
|
||||||
conn.getInputStream() : conn.getErrorStream();
|
|
||||||
|
|
||||||
successful = true;
|
successful = true;
|
||||||
} finally {
|
} finally {
|
||||||
@ -247,6 +246,16 @@ public class HttpRequest implements Closeable, ProgressObservable {
|
|||||||
return conn.getResponseCode();
|
return conn.getResponseCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the response code indicates a successful request.
|
||||||
|
* @return True if response code is 2xx, false otherwise.
|
||||||
|
* @throws IOException on I/O error getting the response code.
|
||||||
|
*/
|
||||||
|
public boolean isSuccessCode() throws IOException {
|
||||||
|
int code = getResponseCode();
|
||||||
|
return code >= 200 && code < 300;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the input stream.
|
* Get the input stream.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user