use better responses
All checks were successful
deploy / deploy (push) Successful in 41s

This commit is contained in:
Lee 2024-04-08 06:48:21 +01:00
parent a2dfd3fc6d
commit 4b4cc8ae54
9 changed files with 57 additions and 55 deletions

@ -2,6 +2,7 @@ package cc.fascinated.controller;
import cc.fascinated.model.player.Player; import cc.fascinated.model.player.Player;
import cc.fascinated.model.player.Skin; import cc.fascinated.model.player.Skin;
import cc.fascinated.model.response.impl.PlayerNotFoundResponse;
import cc.fascinated.service.PlayerService; import cc.fascinated.service.PlayerService;
import cc.fascinated.util.PlayerUtils; import cc.fascinated.util.PlayerUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -29,9 +30,10 @@ public class PlayerController {
@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody
public ResponseEntity<?> getPlayer(@PathVariable String id) { public ResponseEntity<?> getPlayer(@PathVariable String id) {
Player player = playerManagerService.getPlayer(id); Player player = playerManagerService.getPlayer(id);
if (player == null) { if (player == null) { // No player with that id was found
return new ResponseEntity<>(Map.of("error", "Player not found"), HttpStatus.NOT_FOUND); return new PlayerNotFoundResponse().toResponseEntity();
} }
// Return the player
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(cacheControl) .cacheControl(cacheControl)
.body(player); .body(player);
@ -49,11 +51,10 @@ public class PlayerController {
Skin.Parts skinPart = Skin.Parts.fromName(part); Skin.Parts skinPart = Skin.Parts.fromName(part);
partBytes = PlayerUtils.getSkinPartBytes(skin, skinPart, size); partBytes = PlayerUtils.getSkinPartBytes(skin, skinPart, size);
} }
if (partBytes == null) { // Fallback to the default head if (partBytes == null) { // Fallback to the default head
partBytes = PlayerUtils.getSkinPartBytes(Skin.DEFAULT_SKIN, Skin.Parts.HEAD, size); partBytes = PlayerUtils.getSkinPartBytes(Skin.DEFAULT_SKIN, Skin.Parts.HEAD, size);
} }
// Return the part image
return ResponseEntity.ok() return ResponseEntity.ok()
.cacheControl(cacheControl) .cacheControl(cacheControl)
.contentType(MediaType.IMAGE_PNG) .contentType(MediaType.IMAGE_PNG)

@ -1,6 +1,6 @@
package cc.fascinated.exception; package cc.fascinated.exception;
import cc.fascinated.model.response.ErrorResponse; import cc.fascinated.model.response.Response;
import io.micrometer.common.lang.NonNull; import io.micrometer.common.lang.NonNull;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@ -28,6 +28,6 @@ public final class ExceptionControllerAdvice {
message = "An internal error has occurred."; message = "An internal error has occurred.";
} }
ex.printStackTrace(); // Print the stack trace ex.printStackTrace(); // Print the stack trace
return new ResponseEntity<>(new ErrorResponse(status, message), status); return new Response(status, message).toResponseEntity(); // Return the error response
} }
} }

@ -2,6 +2,7 @@ package cc.fascinated.model.player;
import cc.fascinated.config.Config; import cc.fascinated.config.Config;
import cc.fascinated.util.PlayerUtils; import cc.fascinated.util.PlayerUtils;
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;
@ -33,6 +34,7 @@ public class Skin {
/** /**
* The skin image for the skin * The skin image for the skin
*/ */
@JsonIgnore
private final BufferedImage skinImage; private final BufferedImage skinImage;
/** /**

@ -1,40 +0,0 @@
package cc.fascinated.model.response;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.micrometer.common.lang.NonNull;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.springframework.http.HttpStatus;
import java.util.Date;
@NoArgsConstructor
@Setter
@Getter
@ToString
public final class ErrorResponse {
/**
* The status code of this error.
*/
@NonNull
private HttpStatus status;
/**
* The message of this error.
*/
@NonNull private String message;
/**
* The timestamp this error occurred.
*/
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
private Date timestamp;
public ErrorResponse(@NonNull HttpStatus status, @NonNull String message) {
this.status = status;
this.message = message;
timestamp = new Date();
}
}

@ -0,0 +1,31 @@
package cc.fascinated.model.response;
import io.micrometer.common.lang.NonNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.servlet.function.EntityResponse;
@Getter @AllArgsConstructor
public class Response {
/**
* The status code of this error.
*/
private HttpStatus status;
/**
* The message of this error.
*/
private String message;
/**
* Gets this response as a {@link ResponseEntity}.
*
* @return the response entity
*/
public ResponseEntity<?> toResponseEntity() {
return new ResponseEntity<>(this, status);
}
}

@ -0,0 +1,11 @@
package cc.fascinated.model.response.impl;
import cc.fascinated.model.response.Response;
import org.springframework.http.HttpStatus;
public class PlayerNotFoundResponse extends Response {
public PlayerNotFoundResponse() {
super(HttpStatus.NOT_FOUND, "Player not found.");
}
}

@ -24,7 +24,7 @@ public class MojangAPIService {
* @return the profile * @return the profile
*/ */
public MojangProfile getProfile(String id) { public MojangProfile getProfile(String id) {
return WebRequest.get(mojangSessionServerUrl + "/session/minecraft/profile/" + id, MojangProfile.class); return WebRequest.getAsEntity(mojangSessionServerUrl + "/session/minecraft/profile/" + id, MojangProfile.class);
} }
/** /**
@ -35,6 +35,6 @@ public class MojangAPIService {
* @return the profile * @return the profile
*/ */
public MojangUsernameToUuid getUuidFromUsername(String id) { public MojangUsernameToUuid getUuidFromUsername(String id) {
return WebRequest.get(mojangApiUrl + "/users/profiles/minecraft/" + id, MojangUsernameToUuid.class); return WebRequest.getAsEntity(mojangApiUrl + "/users/profiles/minecraft/" + id, MojangUsernameToUuid.class);
} }
} }

@ -27,12 +27,9 @@ public class PlayerUtils {
@SneakyThrows @SneakyThrows
@JsonIgnore @JsonIgnore
public static BufferedImage getSkinImage(String url) { public static BufferedImage getSkinImage(String url) {
HttpRequest request = HttpRequest.newBuilder() HttpResponse<byte[]> response = Main.HTTP_CLIENT.send(HttpRequest.newBuilder(URI.create(url)).build(),
.uri(new URI(url)) HttpResponse.BodyHandlers.ofByteArray());
.GET() byte[] body = response.body();
.build();
byte[] body = Main.HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofByteArray()).body();
if (body == null) { if (body == null) {
return null; return null;
} }

@ -23,7 +23,7 @@ public class WebRequest {
* @return the response * @return the response
* @param <T> the type of the response * @param <T> the type of the response
*/ */
public static <T> T get(String url, Class<T> clazz) { public static <T> T getAsEntity(String url, Class<T> clazz) {
try { try {
ResponseEntity<T> profile = CLIENT.get() ResponseEntity<T> profile = CLIENT.get()
.uri(url) .uri(url)