Skip to content

Commit

Permalink
Hypixel Api Proxy + Profile Id Caching (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
AzureAaron authored Oct 26, 2023
1 parent 0aa9d8b commit 31cfd39
Showing 1 changed file with 44 additions and 4 deletions.
48 changes: 44 additions & 4 deletions src/main/java/de/hysky/skyblocker/utils/Http.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Redirect;
import java.net.http.HttpClient.Version;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
Expand All @@ -15,19 +16,28 @@
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

import org.jetbrains.annotations.NotNull;

import de.hysky.skyblocker.SkyblockerMod;
import net.minecraft.SharedConstants;

/**
* @implNote All http requests are sent using HTTP 2
*/
public class Http {
private static final String NAME_2_UUID = "https://api.minecraftservices.com/minecraft/profile/lookup/name/";
private static final String HYPIXEL_PROXY = "https://api.azureaaron.net/hypixel/";
private static final String USER_AGENT = "Skyblocker/" + SkyblockerMod.VERSION + " (" + SharedConstants.getGameVersion().getName() + ")";
private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.followRedirects(Redirect.NORMAL)
.build();

public static String sendGetRequest(String url) throws IOException, InterruptedException {
return sendCacheableGetRequest(url).content();
}

private static ApiResponse sendCacheableGetRequest(String url) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.header("Accept", "application/json")
Expand All @@ -41,7 +51,7 @@ public static String sendGetRequest(String url) throws IOException, InterruptedE
InputStream decodedInputStream = getDecodedInputStream(response);
String body = new String(decodedInputStream.readAllBytes());

return body;
return new ApiResponse(body, getCacheStatus(response.headers()));
}

public static HttpHeaders sendHeadRequest(String url) throws IOException, InterruptedException {
Expand All @@ -56,8 +66,21 @@ public static HttpHeaders sendHeadRequest(String url) throws IOException, Interr
return response.headers();
}

public static String sendName2UuidRequest(String name) throws IOException, InterruptedException {
return sendGetRequest(NAME_2_UUID + name);
}

/**
* @param endpoint the endpoint - do not include any leading or trailing slashes
* @param query the query string - use empty string if n/a
* @return the requested data with zero pre-processing applied
*/
public static ApiResponse sendHypixelRequest(String endpoint, @NotNull String query) throws IOException, InterruptedException {
return sendCacheableGetRequest(HYPIXEL_PROXY + endpoint + query);
}

private static InputStream getDecodedInputStream(HttpResponse<InputStream> response) {
String encoding = getContentEncoding(response);
String encoding = getContentEncoding(response.headers());

try {
switch (encoding) {
Expand All @@ -75,8 +98,8 @@ private static InputStream getDecodedInputStream(HttpResponse<InputStream> respo
}
}

private static String getContentEncoding(HttpResponse<InputStream> response) {
return response.headers().firstValue("Content-Encoding").orElse("");
private static String getContentEncoding(HttpHeaders headers) {
return headers.firstValue("Content-Encoding").orElse("");
}

public static String getEtag(HttpHeaders headers) {
Expand All @@ -86,4 +109,21 @@ public static String getEtag(HttpHeaders headers) {
public static String getLastModified(HttpHeaders headers) {
return headers.firstValue("Last-Modified").orElse("");
}

/**
* Returns the cache status of the resource
*
* @see <a href="https://developers.cloudflare.com/cache/concepts/default-cache-behavior/#cloudflare-cache-responses">Cloudflare Cache Docs</a>
*/
public static String getCacheStatus(HttpHeaders headers) {
return headers.firstValue("CF-Cache-Status").orElse("UNKNOWN");
}

//TODO If ever needed, we could just replace cache status with the response headers and go from there
public record ApiResponse(String content, String cacheStatus) {

public boolean cached() {
return cacheStatus.equals("HIT");
}
}
}

0 comments on commit 31cfd39

Please sign in to comment.