feat(javaTest): add dispatch audit visualizer
This commit is contained in:
@@ -110,6 +110,22 @@ public final class HistoricalDispatchVisualizerServer {
|
||||
private void route(HttpExchange exchange) throws IOException {
|
||||
String path = exchange.getRequestURI().getPath();
|
||||
String method = exchange.getRequestMethod();
|
||||
if ("/".equals(path) || "/index.html".equals(path)) {
|
||||
requireMethod(method, "GET");
|
||||
writeStatic(exchange, "visualizer/index.html", "text/html; charset=utf-8");
|
||||
return;
|
||||
}
|
||||
if ("/assets/app.css".equals(path)) {
|
||||
requireMethod(method, "GET");
|
||||
writeStatic(exchange, "visualizer/assets/app.css", "text/css; charset=utf-8");
|
||||
return;
|
||||
}
|
||||
if ("/assets/app.js".equals(path)) {
|
||||
requireMethod(method, "GET");
|
||||
writeStatic(exchange, "visualizer/assets/app.js",
|
||||
"application/javascript; charset=utf-8");
|
||||
return;
|
||||
}
|
||||
if ("/api/health".equals(path)) {
|
||||
requireMethod(method, "GET");
|
||||
Map<String, Object> health = new LinkedHashMap<String, Object>();
|
||||
@@ -146,6 +162,40 @@ public final class HistoricalDispatchVisualizerServer {
|
||||
throw new VisualizerHttpException(404, "NOT_FOUND", "请求的审计资源不存在");
|
||||
}
|
||||
|
||||
/**
|
||||
* 从打包后的 classpath 返回审计台资源。调用方只传入固定白名单,浏览器无法借此读取本机文件。
|
||||
*/
|
||||
private void writeStatic(HttpExchange exchange, String resourcePath, String contentType)
|
||||
throws IOException {
|
||||
byte[] body;
|
||||
try (InputStream inputStream = HistoricalDispatchVisualizerServer.class
|
||||
.getClassLoader().getResourceAsStream(resourcePath)) {
|
||||
if (inputStream == null) {
|
||||
throw new VisualizerHttpException(500, "STATIC_RESOURCE_MISSING",
|
||||
"审计页面资源未打包: " + resourcePath);
|
||||
}
|
||||
try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int read;
|
||||
while ((read = inputStream.read(buffer)) >= 0) {
|
||||
output.write(buffer, 0, read);
|
||||
}
|
||||
body = output.toByteArray();
|
||||
}
|
||||
}
|
||||
exchange.getResponseHeaders().set("Content-Type", contentType);
|
||||
exchange.getResponseHeaders().set("Cache-Control", "no-store");
|
||||
exchange.getResponseHeaders().set("Content-Security-Policy",
|
||||
"default-src 'self'; script-src 'self'; style-src 'self'; "
|
||||
+ "img-src 'self' data:; connect-src 'self'; object-src 'none'; "
|
||||
+ "base-uri 'none'; frame-ancestors 'none'");
|
||||
exchange.getResponseHeaders().set("X-Content-Type-Options", "nosniff");
|
||||
exchange.sendResponseHeaders(200, body.length);
|
||||
try (OutputStream output = exchange.getResponseBody()) {
|
||||
output.write(body);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> runSimulation(SimulationCall call) {
|
||||
if (!simulationBusy.compareAndSet(false, true)) {
|
||||
throw new VisualizerHttpException(409, "SIMULATION_BUSY", "已有仿真正在运行");
|
||||
|
||||
Reference in New Issue
Block a user