2025-04-13 21:40:00 +08:00

111 lines
4.0 KiB
Java

package com.example.playertime;
import com.google.gson.Gson;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;
import java.io.*;
import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.*;
import java.util.concurrent.*;
public class WebServer {
private final HttpServer server;
private final PlayerTimeTracker timeTracker;
private final ExecutorService executor = Executors.newFixedThreadPool(4);
private static final Map<String, String> MIME_TYPES = Map.of(
"html", "text/html",
"css", "text/css",
"js", "application/javascript",
"json", "application/json"
);
public WebServer(PlayerTimeTracker timeTracker, int port) throws IOException {
this.timeTracker = timeTracker;
this.server = HttpServer.create(new InetSocketAddress(port), 0);
setupContexts();
}
private void setupContexts() {
// API 端点
// 在 WebServer.java 中修改 /api/stats 的处理
server.createContext("/api/stats", exchange -> {
if (!"GET".equals(exchange.getRequestMethod())) {
sendResponse(exchange, 405, "Method Not Allowed");
return;
}
try {
// 改为使用新的白名单统计方法
Map<String, String> stats = timeTracker.getWhitelistedPlayerStats();
String response = new Gson().toJson(stats);
sendResponse(exchange, 200, response.getBytes(), "application/json");
} catch (Exception e) {
PlayerTimeMod.LOGGER.error("Failed to get stats", e);
sendResponse(exchange, 500, "Internal Server Error");
}
});
// 静态文件服务
server.createContext("/", exchange -> {
try {
String path = exchange.getRequestURI().getPath();
if (path.equals("/")) path = "/index.html";
// 从资源目录加载文件
String resourcePath = "assets/playertime/web" + path;
InputStream is = getClass().getClassLoader().getResourceAsStream(resourcePath);
if (is == null) {
sendResponse(exchange, 404, "Not Found");
return;
}
// 确定内容类型
String extension = path.substring(path.lastIndexOf('.') + 1);
String contentType = MIME_TYPES.getOrDefault(extension, "text/plain");
// 读取文件内容
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int nRead;
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
sendResponse(exchange, 200, buffer.toByteArray(), contentType);
} catch (Exception e) {
PlayerTimeMod.LOGGER.error("Failed to serve resource", e);
sendResponse(exchange, 500, "Internal Server Error");
}
});
server.setExecutor(executor);
}
private void sendResponse(HttpExchange exchange, int code, String response) throws IOException {
sendResponse(exchange, code, response.getBytes(StandardCharsets.UTF_8), "text/plain");
}
private void sendResponse(HttpExchange exchange, int code, byte[] response, String contentType) throws IOException {
exchange.getResponseHeaders().set("Content-Type", contentType);
exchange.sendResponseHeaders(code, response.length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(response);
}
}
public void start() {
server.start();
}
public void stop() {
server.stop(0);
executor.shutdown();
}
}