aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/moulberry/notenoughupdates/util
diff options
context:
space:
mode:
authorRoman / Linnea Gräf <roman.graef@gmail.com>2023-07-21 09:28:48 +0200
committerGitHub <noreply@github.com>2023-07-21 09:28:48 +0200
commit34835697e889799e2b4e97c3bbf0ea73c04d5a64 (patch)
tree421de44a9dcff26b44bab18fcde9ed89ef066f28 /src/main/java/io/github/moulberry/notenoughupdates/util
parent3184880b31e9dc8d8985411468112c6b49e5b480 (diff)
downloadnotenoughupdates-34835697e889799e2b4e97c3bbf0ea73c04d5a64.tar.gz
notenoughupdates-34835697e889799e2b4e97c3bbf0ea73c04d5a64.tar.bz2
notenoughupdates-34835697e889799e2b4e97c3bbf0ea73c04d5a64.zip
Use ursa-minor as API proxy (#762)
* Use ursa-minor as API proxy * Allow setting a ursa server url * Make client aware of x-ursa-expires * Make profile data syncer work using legacy api * Add better header support * Add manual call functionality * Improve callUrsa to allow for raw strings * Save tokens better and add logs on http failure status codes * Remove API key requirement for PV * Make museum in pv also use ursa
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/util')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java48
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java3
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java2
4 files changed, 57 insertions, 11 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
index 4cb1abc8..3b6aed84 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
@@ -58,10 +58,12 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
public class ApiUtil {
@@ -90,16 +92,17 @@ public class ApiUtil {
try {
KeyStore letsEncryptStore = KeyStore.getInstance("JKS");
letsEncryptStore.load(ApiUtil.class.getResourceAsStream("/neukeystore.jks"), "neuneu".toCharArray());
- ctx = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
kmf.init(letsEncryptStore, null);
tmf.init(letsEncryptStore);
+ ctx = SSLContext.getInstance("TLS");
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException |
IOException | CertificateException e) {
System.out.println("Failed to load NEU keystore. A lot of API requests won't work");
e.printStackTrace();
+ ctx = null;
}
}
@@ -129,6 +132,8 @@ public class ApiUtil {
private Duration maxCacheAge = Duration.ofSeconds(500);
private String method = "GET";
private String postData = null;
+ private final Map<String, String> headers = new HashMap<>();
+ private Map<String, List<String>> responseHeaders = new HashMap<>();
private String postContentType = null;
public Request method(String method) {
@@ -136,6 +141,11 @@ public class ApiUtil {
return this;
}
+ public Request header(String key, String value) {
+ this.headers.put(key, value);
+ return this;
+ }
+
/**
* Specify a cache timeout of {@code null} to signify an uncacheable request.
* Non {@code GET} requests are always uncacheable.
@@ -196,9 +206,17 @@ public class ApiUtil {
return new ApiCache.CacheKey(baseUrl, queryArguments, shouldGunzip);
}
+ /**
+ * Note: This map may be empty on cache hits.
+ */
+ public Map<String, List<String>> getResponseHeaders() {
+ return responseHeaders;
+ }
+
private CompletableFuture<String> requestString0() {
return buildUrl().thenApplyAsync(url -> {
InputStream inputStream = null;
+ int httpStatusCode = 200;
URLConnection conn = null;
try {
try {
@@ -212,6 +230,9 @@ public class ApiUtil {
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
conn.setRequestProperty("User-Agent", getUserAgent());
+ for (Map.Entry<String, String> header : headers.entrySet()) {
+ conn.setRequestProperty(header.getKey(), header.getValue());
+ }
if (this.postContentType != null) {
conn.setRequestProperty("Content-Type", this.postContentType);
}
@@ -228,16 +249,33 @@ public class ApiUtil {
}
}
- inputStream = conn.getInputStream();
+ if (conn instanceof HttpURLConnection) {
+ HttpURLConnection httpConn = (HttpURLConnection) conn;
+ httpStatusCode = httpConn.getResponseCode();
+ if (httpStatusCode >= 400) {
+ inputStream = httpConn.getErrorStream();
+ }
+ }
+ if (inputStream == null)
+ inputStream = conn.getInputStream();
if (shouldGunzip || "gzip".equals(conn.getContentEncoding())) {
inputStream = new GZIPInputStream(inputStream);
}
+ responseHeaders = conn.getHeaderFields().entrySet().stream()
+ .collect(Collectors.toMap(
+ it -> it.getKey() == null ? null : it.getKey().toLowerCase(Locale.ROOT),
+ it -> new ArrayList<>(it.getValue())
+ ));
// While the assumption of UTF8 isn't always true; it *should* always be true.
// Not in the sense that this will hold in most cases (although that as well),
// but in the sense that any violation of this better have a good reason.
- return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ String response = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ if (httpStatusCode >= 400) {
+ throw new HttpStatusCodeException(url, httpStatusCode, response);
+ }
+ return response;
} finally {
try {
if (inputStream != null) {
@@ -298,13 +336,15 @@ public class ApiUtil {
}
public static void patchHttpsRequest(HttpsURLConnection connection) {
- connection.setSSLSocketFactory(ctx.getSocketFactory());
+ if (ctx != null && connection != null)
+ connection.setSSLSocketFactory(ctx.getSocketFactory());
}
public Request request() {
return new Request();
}
+ @Deprecated
public Request newHypixelApiRequest(String apiPath) {
return newAnonymousHypixelApiRequest(apiPath)
.queryArgument("key", NotEnoughUpdates.INSTANCE.config.apiData.apiKey);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java
index e5d00a66..d73a500c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java
@@ -22,7 +22,6 @@ package io.github.moulberry.notenoughupdates.util;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
import net.minecraft.client.Minecraft;
-import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import java.util.function.Consumer;
@@ -34,7 +33,7 @@ public class NEUDebugLogger {
public static boolean allFlagsEnabled = false;
private static void chatLogger(String message) {
- Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message);
+ mc.addScheduledTask(() -> Utils.addChatMessage(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message));
}
public static boolean isFlagEnabled(NEUDebugFlag flag) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
index 67ed7c7b..ed88a6a5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
@@ -19,6 +19,7 @@
package io.github.moulberry.notenoughupdates.util;
+import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.profileviewer.SkyblockProfiles;
import net.minecraft.client.Minecraft;
@@ -89,9 +90,15 @@ public class ProfileApiSyncer {
if (Minecraft.getMinecraft().thePlayer == null) return;
String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
- NotEnoughUpdates.profileViewer.getOrLoadSkyblockProfiles(uuid, (profile) -> {
- for (Consumer<SkyblockProfiles> c : finishSyncCallbacks.values()) c.accept(profile);
- finishSyncCallbacks.clear();
- });
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newHypixelApiRequest("/skyblock/profiles")
+ .queryArgument("uuid", uuid)
+ .requestJson()
+ .thenAcceptAsync((profile) -> {
+ SkyblockProfiles skyblockProfiles = new SkyblockProfiles(NotEnoughUpdates.profileViewer, uuid);
+ for (Consumer<SkyblockProfiles> c : finishSyncCallbacks.values())
+ c.accept((skyblockProfiles));
+ finishSyncCallbacks.clear();
+ }, MinecraftExecutor.OnThread);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
index 2d637ab8..e5a0e1b8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
@@ -459,7 +459,7 @@ public class SBInfo {
public void updateMayor() {
NotEnoughUpdates.INSTANCE.manager.apiUtils
- .newHypixelApiRequest("resources/skyblock/election")
+ .newAnonymousHypixelApiRequest("resources/skyblock/election")
.requestJson()
.thenAccept(newJson -> mayorJson = newJson);
}