- Implement file saving to disk in `NotificationServer` with optional UUID-based organization. - Use `Config` to configure `DOWNLOAD_DIR` and `PORT` for better flexibility. - Update HTTP responses for improved clarity on file download and save operations.
171 lines
5.5 KiB
Java
171 lines
5.5 KiB
Java
package com.alttd.webinterface.http;
|
|
|
|
import com.alttd.webinterface.config.Config;
|
|
import com.alttd.webinterface.web_interact.FileDownloadService;
|
|
import io.javalin.Javalin;
|
|
import io.javalin.http.Context;
|
|
import io.javalin.http.HttpStatus;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.Optional;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
/**
|
|
* HTTP server that exposes the /notify/<file>.json endpoint.
|
|
*/
|
|
@Slf4j
|
|
public class NotificationServer {
|
|
private final int port;
|
|
private Javalin app;
|
|
|
|
/**
|
|
* Creates a new NotificationServer that listens on the specified port.
|
|
*
|
|
* @param port The port to listen on
|
|
*/
|
|
public NotificationServer(int port) {
|
|
this.port = port;
|
|
}
|
|
|
|
/**
|
|
* Starts the server.
|
|
*/
|
|
public void startServer() {
|
|
try {
|
|
app = Javalin.create(config -> {
|
|
config.showJavalinBanner = false;
|
|
}).start(port);
|
|
|
|
app.get("/notify/{file}.json", this::handleNotifyRequest);
|
|
app.get("/notify/{uuid}/{file}.json", this::handleNotifyRequestUuid);
|
|
|
|
log.info("NotificationServer started on port {}", port);
|
|
} catch (Exception e) {
|
|
log.error("Failed to start NotificationServer", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stops the server.
|
|
*/
|
|
public void stopServer() {
|
|
if (app != null) {
|
|
app.stop();
|
|
log.info("NotificationServer stopped");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles requests to the /notify/<file>.json endpoint.
|
|
*/
|
|
private void handleNotifyRequest(Context ctx) {
|
|
String uri = ctx.path();
|
|
log.info("Received download request: {} {}", ctx.method(), uri);
|
|
|
|
String fileName = ctx.pathParam("file") + ".json";
|
|
log.info("Requested file: {}", fileName);
|
|
|
|
CompletableFuture<Optional<byte[]>> optionalCompletableFuture = FileDownloadService.downloadFileAsync(fileName);
|
|
downloadFile(ctx, optionalCompletableFuture);
|
|
}
|
|
|
|
/**
|
|
* Handles requests to the /notify/<file>.json endpoint.
|
|
*/
|
|
private void handleNotifyRequestUuid(Context ctx) {
|
|
String uri = ctx.path();
|
|
log.info("Received UUID request: {} {}", ctx.method(), uri);
|
|
|
|
String stringUUID = ctx.pathParam("uuid");
|
|
log.info("Requested uuid: {}", stringUUID);
|
|
|
|
UUID uuid;
|
|
try {
|
|
uuid = UUID.fromString(stringUUID);
|
|
} catch (Exception e) {
|
|
log.error("Invalid UUID: {}", stringUUID, e);
|
|
ctx.status(HttpStatus.BAD_REQUEST);
|
|
ctx.contentType("text/plain");
|
|
ctx.result("Invalid UUID format");
|
|
return;
|
|
}
|
|
|
|
String fileName = ctx.pathParam("file") + ".json";
|
|
log.info("Requested uuid file: {}", fileName);
|
|
|
|
CompletableFuture<Optional<byte[]>> optionalCompletableFuture = FileDownloadService.downloadFileAsync(uuid, fileName);
|
|
downloadFile(ctx, optionalCompletableFuture);
|
|
}
|
|
|
|
private void downloadFile(Context ctx, CompletableFuture<Optional<byte[]>> optionalCompletableFuture) {
|
|
optionalCompletableFuture.thenAccept(fileData -> {
|
|
if (fileData.isPresent()) {
|
|
String fileName = ctx.pathParam("file") + ".json";
|
|
String uuid = null;
|
|
try {
|
|
uuid = ctx.pathParam("uuid");
|
|
} catch (Exception ignored) {
|
|
log.debug("UUID not present");
|
|
}
|
|
|
|
boolean saved = saveFileToDisk(fileData.get(), fileName, uuid);
|
|
|
|
if (saved) {
|
|
ctx.status(HttpStatus.OK);
|
|
ctx.contentType("text/plain");
|
|
ctx.result("File downloaded and saved successfully");
|
|
} else {
|
|
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
ctx.contentType("text/plain");
|
|
ctx.result("Failed to save file to disk");
|
|
}
|
|
} else {
|
|
ctx.status(HttpStatus.NOT_FOUND);
|
|
ctx.contentType("text/plain");
|
|
ctx.result("File not found or download failed");
|
|
}
|
|
}).exceptionally(e -> {
|
|
log.error("Error downloading file", e);
|
|
ctx.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
ctx.contentType("text/plain");
|
|
ctx.result("Failed to handle download");
|
|
return null;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Saves the downloaded file to disk.
|
|
*
|
|
* @param fileData The binary content of the file
|
|
* @param fileName The name of the file
|
|
* @param uuid Optional UUID for organizing files
|
|
* @return true if the file was saved successfully, false otherwise
|
|
*/
|
|
private boolean saveFileToDisk(byte[] fileData, String fileName, String uuid) {
|
|
try {
|
|
Path basePath = Paths.get(Config.DOWNLOAD_DIR);
|
|
|
|
Path filePath;
|
|
if (uuid != null) {
|
|
filePath = basePath.resolve(uuid).resolve(fileName);
|
|
} else {
|
|
filePath = basePath.resolve(fileName);
|
|
}
|
|
|
|
Files.createDirectories(filePath.getParent());
|
|
Files.write(filePath, fileData);
|
|
|
|
log.info("File saved to: {}", filePath.toAbsolutePath());
|
|
return true;
|
|
} catch (IOException e) {
|
|
log.error("Error saving file to disk", e);
|
|
return false;
|
|
}
|
|
}
|
|
}
|