mirror of
https://github.com/SKCraft/Launcher.git
synced 2024-11-24 12:16:28 +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;
|
||||
boolean first = true;
|
||||
IOException lastException = null;
|
||||
HttpRequest.PartialDownloadInfo retryDetails = null;
|
||||
|
||||
do {
|
||||
for (URL url : urls) {
|
||||
@ -249,17 +248,10 @@ public class HttpDownloader implements Downloader {
|
||||
first = false;
|
||||
|
||||
try {
|
||||
request = HttpRequest.get(url);
|
||||
request.setResumeInfo(retryDetails).execute().expectResponseCode(200).saveContent(file);
|
||||
tryDownloadFrom(url, file, null, 0);
|
||||
return;
|
||||
} catch (IOException 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);
|
||||
@ -267,6 +259,27 @@ public class HttpDownloader implements Downloader {
|
||||
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
|
||||
public double getProgress() {
|
||||
HttpRequest request = this.request;
|
||||
|
@ -117,8 +117,7 @@ public class HttpRequest implements Closeable, ProgressObservable {
|
||||
|
||||
conn = this.runRequest(url);
|
||||
|
||||
inputStream = conn.getResponseCode() == HttpURLConnection.HTTP_OK ?
|
||||
conn.getInputStream() : conn.getErrorStream();
|
||||
inputStream = isSuccessCode() ? conn.getInputStream() : conn.getErrorStream();
|
||||
|
||||
successful = true;
|
||||
} finally {
|
||||
@ -247,6 +246,16 @@ public class HttpRequest implements Closeable, ProgressObservable {
|
||||
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.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user