Use GitHub proxy fallback for update checker (#4818)

This commit is contained in:
MD 2022-02-26 22:09:54 +00:00 committed by GitHub
parent bc2da98703
commit c3b994808f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 56 additions and 29 deletions

View File

@ -1,7 +1,6 @@
package com.earth2me.essentials.updatecheck;
import com.earth2me.essentials.Essentials;
import com.google.common.base.Charsets;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
@ -13,6 +12,7 @@ import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@ -23,6 +23,12 @@ public final class UpdateChecker {
private static final String REPO = "EssentialsX/Essentials";
private static final String BRANCH = "2.x";
private static final String LATEST_RELEASE_URL = "https://api.github.com/repos/" + REPO + "/releases/latest";
private static final String LATEST_RELEASE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/releases/latest";
// 0 = base for comparison, 1 = head for comparison - *not* the same as what this class calls them
private static final String DISTANCE_URL = "https://api.github.com/repos/EssentialsX/Essentials/compare/{0}...{1}";
private static final String DISTANCE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/compare/{0}/{1}";
private final Essentials ess;
private final String versionIdentifier;
private final String versionBranch;
@ -89,8 +95,7 @@ public final class UpdateChecker {
new Thread(() -> {
catchBlock:
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/releases/latest").openConnection();
connection.connect();
final HttpURLConnection connection = tryRequestWithFallback(LATEST_RELEASE_URL, LATEST_RELEASE_PROXY_URL);
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
// Locally built?
@ -102,7 +107,7 @@ public final class UpdateChecker {
break catchBlock;
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
latestRelease = new Gson().fromJson(reader, JsonObject.class).get("tag_name").getAsString();
pendingReleaseFuture.complete(cachedRelease = fetchDistance(latestRelease, getVersionIdentifier()));
} catch (JsonSyntaxException | NumberFormatException e) {
@ -137,10 +142,54 @@ public final class UpdateChecker {
return latestRelease;
}
private HttpURLConnection tryRequestWithFallback(final String githubUrl, final String fallbackUrl) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(githubUrl).openConnection();
try {
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_INTERNAL_ERROR && connection.getResponseCode() != HttpURLConnection.HTTP_FORBIDDEN) {
// Connection succeeded without any errors from GitHub's side.
return connection;
}
} catch (IOException ignored) {
}
// Connection failed, GitHub's down or we hit a ratelimit, so use the fallback URL
// If the fallback fails, let the exception or error status bubble up
connection = (HttpURLConnection) new URL(fallbackUrl).openConnection();
connection.connect();
return connection;
}
private RemoteVersion tryProcessDistance(final HttpURLConnection connection) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
switch (obj.get("status").getAsString()) {
case "identical": {
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
}
case "ahead": {
return new RemoteVersion(BranchStatus.AHEAD, 0);
}
case "behind": {
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
}
case "diverged": {
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
}
default: {
return new RemoteVersion(BranchStatus.UNKNOWN);
}
}
} catch (JsonSyntaxException | NumberFormatException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);
}
}
private RemoteVersion fetchDistance(final String head, final String hash) {
try {
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/compare/" + head + "..." + hash).openConnection();
connection.connect();
final HttpURLConnection connection = tryRequestWithFallback(MessageFormat.format(DISTANCE_URL, head, hash), MessageFormat.format(DISTANCE_PROXY_URL, head, hash));
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
// Locally built?
@ -150,29 +199,7 @@ public final class UpdateChecker {
return new RemoteVersion(BranchStatus.ERROR);
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
switch (obj.get("status").getAsString()) {
case "identical": {
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
}
case "ahead": {
return new RemoteVersion(BranchStatus.AHEAD, 0);
}
case "behind": {
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
}
case "diverged": {
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
}
default: {
return new RemoteVersion(BranchStatus.UNKNOWN);
}
}
} catch (JsonSyntaxException | NumberFormatException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);
}
return tryProcessDistance(connection);
} catch (IOException e) {
e.printStackTrace();
return new RemoteVersion(BranchStatus.ERROR);