Skip to content

Commit c3b9948

Browse files
authored
Use GitHub proxy fallback for update checker (#4818)
1 parent bc2da98 commit c3b9948

1 file changed

Lines changed: 56 additions & 29 deletions

File tree

Essentials/src/main/java/com/earth2me/essentials/updatecheck/UpdateChecker.java

Lines changed: 56 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.earth2me.essentials.updatecheck;
22

33
import com.earth2me.essentials.Essentials;
4-
import com.google.common.base.Charsets;
54
import com.google.gson.Gson;
65
import com.google.gson.JsonObject;
76
import com.google.gson.JsonSyntaxException;
@@ -13,6 +12,7 @@
1312
import java.net.HttpURLConnection;
1413
import java.net.URL;
1514
import java.nio.charset.StandardCharsets;
15+
import java.text.MessageFormat;
1616
import java.util.List;
1717
import java.util.concurrent.CompletableFuture;
1818
import java.util.stream.Collectors;
@@ -23,6 +23,12 @@ public final class UpdateChecker {
2323
private static final String REPO = "EssentialsX/Essentials";
2424
private static final String BRANCH = "2.x";
2525

26+
private static final String LATEST_RELEASE_URL = "https://api.github.com/repos/" + REPO + "/releases/latest";
27+
private static final String LATEST_RELEASE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/releases/latest";
28+
// 0 = base for comparison, 1 = head for comparison - *not* the same as what this class calls them
29+
private static final String DISTANCE_URL = "https://api.github.com/repos/EssentialsX/Essentials/compare/{0}...{1}";
30+
private static final String DISTANCE_PROXY_URL = "https://webapi.essentialsx.net/api/v1/github/essx-v2/compare/{0}/{1}";
31+
2632
private final Essentials ess;
2733
private final String versionIdentifier;
2834
private final String versionBranch;
@@ -89,8 +95,7 @@ public CompletableFuture<RemoteVersion> fetchLatestRelease() {
8995
new Thread(() -> {
9096
catchBlock:
9197
try {
92-
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/releases/latest").openConnection();
93-
connection.connect();
98+
final HttpURLConnection connection = tryRequestWithFallback(LATEST_RELEASE_URL, LATEST_RELEASE_PROXY_URL);
9499

95100
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
96101
// Locally built?
@@ -102,7 +107,7 @@ public CompletableFuture<RemoteVersion> fetchLatestRelease() {
102107
break catchBlock;
103108
}
104109

105-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
110+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
106111
latestRelease = new Gson().fromJson(reader, JsonObject.class).get("tag_name").getAsString();
107112
pendingReleaseFuture.complete(cachedRelease = fetchDistance(latestRelease, getVersionIdentifier()));
108113
} catch (JsonSyntaxException | NumberFormatException e) {
@@ -137,10 +142,54 @@ public String getLatestRelease() {
137142
return latestRelease;
138143
}
139144

140-
private RemoteVersion fetchDistance(final String head, final String hash) {
145+
private HttpURLConnection tryRequestWithFallback(final String githubUrl, final String fallbackUrl) throws IOException {
146+
HttpURLConnection connection = (HttpURLConnection) new URL(githubUrl).openConnection();
141147
try {
142-
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.github.com/repos/" + REPO + "/compare/" + head + "..." + hash).openConnection();
143148
connection.connect();
149+
if (connection.getResponseCode() != HttpURLConnection.HTTP_INTERNAL_ERROR && connection.getResponseCode() != HttpURLConnection.HTTP_FORBIDDEN) {
150+
// Connection succeeded without any errors from GitHub's side.
151+
return connection;
152+
}
153+
} catch (IOException ignored) {
154+
}
155+
156+
// Connection failed, GitHub's down or we hit a ratelimit, so use the fallback URL
157+
// If the fallback fails, let the exception or error status bubble up
158+
connection = (HttpURLConnection) new URL(fallbackUrl).openConnection();
159+
connection.connect();
160+
161+
return connection;
162+
}
163+
164+
private RemoteVersion tryProcessDistance(final HttpURLConnection connection) throws IOException {
165+
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
166+
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
167+
switch (obj.get("status").getAsString()) {
168+
case "identical": {
169+
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
170+
}
171+
case "ahead": {
172+
return new RemoteVersion(BranchStatus.AHEAD, 0);
173+
}
174+
case "behind": {
175+
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
176+
}
177+
case "diverged": {
178+
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
179+
}
180+
default: {
181+
return new RemoteVersion(BranchStatus.UNKNOWN);
182+
}
183+
}
184+
} catch (JsonSyntaxException | NumberFormatException e) {
185+
e.printStackTrace();
186+
return new RemoteVersion(BranchStatus.ERROR);
187+
}
188+
}
189+
190+
private RemoteVersion fetchDistance(final String head, final String hash) {
191+
try {
192+
final HttpURLConnection connection = tryRequestWithFallback(MessageFormat.format(DISTANCE_URL, head, hash), MessageFormat.format(DISTANCE_PROXY_URL, head, hash));
144193

145194
if (connection.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
146195
// Locally built?
@@ -150,29 +199,7 @@ private RemoteVersion fetchDistance(final String head, final String hash) {
150199
return new RemoteVersion(BranchStatus.ERROR);
151200
}
152201

153-
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charsets.UTF_8))) {
154-
final JsonObject obj = new Gson().fromJson(reader, JsonObject.class);
155-
switch (obj.get("status").getAsString()) {
156-
case "identical": {
157-
return new RemoteVersion(BranchStatus.IDENTICAL, 0);
158-
}
159-
case "ahead": {
160-
return new RemoteVersion(BranchStatus.AHEAD, 0);
161-
}
162-
case "behind": {
163-
return new RemoteVersion(BranchStatus.BEHIND, obj.get("behind_by").getAsInt());
164-
}
165-
case "diverged": {
166-
return new RemoteVersion(BranchStatus.DIVERGED, obj.get("behind_by").getAsInt());
167-
}
168-
default: {
169-
return new RemoteVersion(BranchStatus.UNKNOWN);
170-
}
171-
}
172-
} catch (JsonSyntaxException | NumberFormatException e) {
173-
e.printStackTrace();
174-
return new RemoteVersion(BranchStatus.ERROR);
175-
}
202+
return tryProcessDistance(connection);
176203
} catch (IOException e) {
177204
e.printStackTrace();
178205
return new RemoteVersion(BranchStatus.ERROR);

0 commit comments

Comments
 (0)