impl etags

This commit is contained in:
Lee 2024-04-19 20:46:30 +01:00
parent 4dc263961d
commit d0cfd03ad9
16 changed files with 50 additions and 48 deletions

@ -25,8 +25,11 @@ public class MojangController {
@ResponseBody @ResponseBody
@GetMapping(value = "/status") @GetMapping(value = "/status")
public ResponseEntity<CachedEndpointStatus> getStatus() { public ResponseEntity<CachedEndpointStatus> getStatus() {
CachedEndpointStatus status = mojangService.getMojangApiStatus();
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(1, TimeUnit.MINUTES)) .cacheControl(CacheControl.maxAge(1, TimeUnit.MINUTES))
.body(mojangService.getMojangApiStatus()); .eTag(String.valueOf(status.hashCode()))
.body(status);
} }
} }

@ -31,18 +31,24 @@ public class PlayerController {
@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> getPlayer( public ResponseEntity<?> getPlayer(
@Parameter(description = "The UUID or Username of the player", example = "ImFascinated") @PathVariable String id) { @Parameter(description = "The UUID or Username of the player", example = "ImFascinated") @PathVariable String id) {
CachedPlayer player = playerService.getPlayer(id);
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS)) .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
.body(playerService.getPlayer(id)); .eTag(String.valueOf(player.hashCode()))
.body(player);
} }
@ResponseBody @ResponseBody
@GetMapping(value = "/uuid/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(value = "/uuid/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CachedPlayerName> getPlayerUuid( public ResponseEntity<CachedPlayerName> getPlayerUuid(
@Parameter(description = "The UUID or Username of the player", example = "ImFascinated") @PathVariable String id) { @Parameter(description = "The UUID or Username of the player", example = "ImFascinated") @PathVariable String id) {
CachedPlayerName player = playerService.usernameToUuid(id);
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(6, TimeUnit.HOURS)) .cacheControl(CacheControl.maxAge(6, TimeUnit.HOURS))
.body(playerService.usernameToUuid(id)); .eTag(String.valueOf(player.hashCode()))
.body(player);
} }
@GetMapping(value = "/{part}/{id}") @GetMapping(value = "/{part}/{id}")
@ -61,6 +67,7 @@ public class PlayerController {
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS)) .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
.contentType(MediaType.IMAGE_PNG) .contentType(MediaType.IMAGE_PNG)
.header(HttpHeaders.CONTENT_DISPOSITION, dispositionHeader.formatted(player.getUsername())) .header(HttpHeaders.CONTENT_DISPOSITION, dispositionHeader.formatted(player.getUsername()))
.eTag(String.valueOf(player.hashCode()))
.body(playerService.getSkinPart(player, part, overlays, size).getBytes()); .body(playerService.getSkinPart(player, part, overlays, size).getBytes());
} }
} }

@ -12,6 +12,7 @@ import xyz.mcutils.backend.model.cache.CachedMinecraftServer;
import xyz.mcutils.backend.service.MojangService; import xyz.mcutils.backend.service.MojangService;
import xyz.mcutils.backend.service.ServerService; import xyz.mcutils.backend.service.ServerService;
import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -34,9 +35,12 @@ public class ServerController {
public ResponseEntity<CachedMinecraftServer> getServer( public ResponseEntity<CachedMinecraftServer> getServer(
@Parameter(description = "The platform of the server", example = "java") @PathVariable String platform, @Parameter(description = "The platform of the server", example = "java") @PathVariable String platform,
@Parameter(description = "The hostname and port of the server", example = "aetheria.cc") @PathVariable String hostname) { @Parameter(description = "The hostname and port of the server", example = "aetheria.cc") @PathVariable String hostname) {
CachedMinecraftServer server = serverService.getServer(platform, hostname);
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES)) .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES))
.body(serverService.getServer(platform, hostname)); .eTag(String.valueOf(server.hashCode()))
.body(server);
} }
@ResponseBody @ResponseBody
@ -46,11 +50,14 @@ public class ServerController {
@Parameter(description = "Whether to download the image") @RequestParam(required = false, defaultValue = "false") boolean download) { @Parameter(description = "Whether to download the image") @RequestParam(required = false, defaultValue = "false") boolean download) {
String dispositionHeader = download ? "attachment; filename=%s.png" : "inline; filename=%s.png"; String dispositionHeader = download ? "attachment; filename=%s.png" : "inline; filename=%s.png";
byte[] favicon = serverService.getServerFavicon(hostname);
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS)) .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
.contentType(MediaType.IMAGE_PNG) .contentType(MediaType.IMAGE_PNG)
.header(HttpHeaders.CONTENT_DISPOSITION, dispositionHeader.formatted(hostname)) .header(HttpHeaders.CONTENT_DISPOSITION, dispositionHeader.formatted(hostname))
.body(serverService.getServerFavicon(hostname)); .eTag(String.valueOf(Arrays.hashCode(favicon)))
.body(favicon);
} }
@ResponseBody @ResponseBody
@ -59,6 +66,7 @@ public class ServerController {
@Parameter(description = "The hostname of the server", example = "aetheria.cc") @PathVariable String hostname) { @Parameter(description = "The hostname of the server", example = "aetheria.cc") @PathVariable String hostname) {
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS)) .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
.eTag(String.valueOf(hostname.hashCode()))
.body(Map.of( .body(Map.of(
"blocked", mojangService.isServerBlocked(hostname) "blocked", mojangService.isServerBlocked(hostname)
)); ));

@ -2,10 +2,7 @@ package xyz.mcutils.backend.model.cache;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Getter; import lombok.*;
import lombok.NonNull;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.RedisHash;
import xyz.mcutils.backend.common.CachedResponse; import xyz.mcutils.backend.common.CachedResponse;
@ -14,7 +11,7 @@ import xyz.mcutils.backend.model.mojang.EndpointStatus;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
@Setter @Getter @ToString @Setter @Getter @EqualsAndHashCode(callSuper = false)
@RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds) @RedisHash(value = "mojangEndpointStatus", timeToLive = 60L) // 1 minute (in seconds)
public class CachedEndpointStatus extends CachedResponse implements Serializable { public class CachedEndpointStatus extends CachedResponse implements Serializable {

@ -13,8 +13,7 @@ import java.io.Serializable;
/** /**
* @author Braydon * @author Braydon
*/ */
@Setter @Getter @ToString @Setter @Getter @EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@RedisHash(value = "server", timeToLive = 60L) // 1 minute (in seconds) @RedisHash(value = "server", timeToLive = 60L) // 1 minute (in seconds)
public class CachedMinecraftServer extends CachedResponse implements Serializable { public class CachedMinecraftServer extends CachedResponse implements Serializable {
/** /**

@ -2,9 +2,7 @@ package xyz.mcutils.backend.model.cache;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Getter; import lombok.*;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.RedisHash;
import xyz.mcutils.backend.common.CachedResponse; import xyz.mcutils.backend.common.CachedResponse;
@ -18,8 +16,7 @@ import java.util.UUID;
* *
* @author Braydon * @author Braydon
*/ */
@Setter @Getter @Setter @Getter @EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@RedisHash(value = "player", timeToLive = 60L * 60L) // 1 hour (in seconds) @RedisHash(value = "player", timeToLive = 60L * 60L) // 1 hour (in seconds)
public class CachedPlayer extends CachedResponse implements Serializable { public class CachedPlayer extends CachedResponse implements Serializable {
/** /**

@ -1,8 +1,7 @@
package xyz.mcutils.backend.model.cache; package xyz.mcutils.backend.model.cache;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter; import lombok.*;
import lombok.ToString;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.RedisHash;
import xyz.mcutils.backend.common.CachedResponse; import xyz.mcutils.backend.common.CachedResponse;
@ -12,8 +11,8 @@ import java.util.UUID;
/** /**
* @author Braydon * @author Braydon
*/ */
@Getter @Setter
@ToString @Getter @EqualsAndHashCode(callSuper = false)
@RedisHash(value = "playerName", timeToLive = 60L * 60L * 6) // 6 hours (in seconds) @RedisHash(value = "playerName", timeToLive = 60L * 60L * 6) // 6 hours (in seconds)
public class CachedPlayerName extends CachedResponse { public class CachedPlayerName extends CachedResponse {
/** /**

@ -1,15 +1,11 @@
package xyz.mcutils.backend.model.cache; package xyz.mcutils.backend.model.cache;
import lombok.AllArgsConstructor; import lombok.*;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash; import org.springframework.data.redis.core.RedisHash;
@Setter
@Getter
@AllArgsConstructor @AllArgsConstructor
@Setter @Getter @EqualsAndHashCode
@RedisHash(value = "playerSkinPart", timeToLive = 60L * 60L) // 1 hour (in seconds) @RedisHash(value = "playerSkinPart", timeToLive = 60L * 60L) // 1 hour (in seconds)
public class CachedPlayerSkinPart { public class CachedPlayerSkinPart {

@ -1,13 +1,10 @@
package xyz.mcutils.backend.model.dns; package xyz.mcutils.backend.model.dns;
import io.micrometer.common.lang.NonNull; import io.micrometer.common.lang.NonNull;
import lombok.AllArgsConstructor; import lombok.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter @Getter
@NoArgsConstructor @AllArgsConstructor @NoArgsConstructor @AllArgsConstructor
@Setter @Getter @EqualsAndHashCode
public abstract class DNSRecord { public abstract class DNSRecord {
/** /**
* The type of this record. * The type of this record.

@ -1,14 +1,11 @@
package xyz.mcutils.backend.model.mojang; package xyz.mcutils.backend.model.mojang;
import lombok.AllArgsConstructor; import lombok.*;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import java.util.Map; import java.util.Map;
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Setter @Getter @Setter @EqualsAndHashCode
public class EndpointStatus { public class EndpointStatus {
/** /**

@ -2,9 +2,11 @@ package xyz.mcutils.backend.model.player;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
@Getter @AllArgsConstructor @AllArgsConstructor
@Getter @EqualsAndHashCode
public class Cape { public class Cape {
/** /**

@ -1,6 +1,7 @@
package xyz.mcutils.backend.model.player; package xyz.mcutils.backend.model.player;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import xyz.mcutils.backend.common.Tuple; import xyz.mcutils.backend.common.Tuple;
@ -10,7 +11,8 @@ import xyz.mcutils.backend.model.token.MojangProfileToken;
import java.util.UUID; import java.util.UUID;
@Getter @AllArgsConstructor @NoArgsConstructor @AllArgsConstructor @NoArgsConstructor
@Getter @EqualsAndHashCode
public class Player { public class Player {
/** /**

@ -1,14 +1,14 @@
package xyz.mcutils.backend.model.response; package xyz.mcutils.backend.model.response;
import io.micrometer.common.lang.NonNull; import io.micrometer.common.lang.NonNull;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import java.util.Date; import java.util.Date;
@Getter @Getter @ToString @EqualsAndHashCode
@ToString
public class ErrorResponse { public class ErrorResponse {
/** /**
* The status code of this error. * The status code of this error.

@ -14,7 +14,7 @@ import xyz.mcutils.backend.model.token.JavaServerStatusToken;
/** /**
* @author Braydon * @author Braydon
*/ */
@Setter @Getter @Setter @Getter @EqualsAndHashCode(callSuper = false)
public final class JavaMinecraftServer extends MinecraftServer { public final class JavaMinecraftServer extends MinecraftServer {
/** /**

@ -1,10 +1,7 @@
package xyz.mcutils.backend.model.server; package xyz.mcutils.backend.model.server;
import io.micrometer.common.lang.NonNull; import io.micrometer.common.lang.NonNull;
import lombok.AllArgsConstructor; import lombok.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import xyz.mcutils.backend.common.ColorUtils; import xyz.mcutils.backend.common.ColorUtils;
import xyz.mcutils.backend.model.dns.DNSRecord; import xyz.mcutils.backend.model.dns.DNSRecord;
import xyz.mcutils.backend.service.pinger.MinecraftServerPinger; import xyz.mcutils.backend.service.pinger.MinecraftServerPinger;
@ -18,7 +15,7 @@ import java.util.UUID;
* @author Braydon * @author Braydon
*/ */
@AllArgsConstructor @AllArgsConstructor
@Getter @Setter @Getter @Setter @EqualsAndHashCode
public class MinecraftServer { public class MinecraftServer {
/** /**

@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2; import lombok.extern.log4j.Log4j2;
@ -18,7 +19,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
@AllArgsConstructor @NoArgsConstructor @AllArgsConstructor @NoArgsConstructor
@Getter @Log4j2 @Getter @Log4j2 @EqualsAndHashCode
public class Skin { public class Skin {
/** /**
* The URL for the skin * The URL for the skin