package com.hubilon.handler; import com.hubilon.config.ConfigService; import com.hubilon.util.DebugState; import com.hubilon.util.HttpResponses; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public final class ConfigHandler implements HttpHandler { private final ConfigService configService; private final String preferredConfig; private final DebugState debugState; public ConfigHandler(ConfigService configService, String preferredConfig, DebugState debugState) { this.configService = configService; this.preferredConfig = preferredConfig; this.debugState = debugState; } @Override public void handle(HttpExchange exchange) throws IOException { List available = configService.listConfigFiles(); String requested = queryParam(exchange, "file"); if (requested == null || requested.isBlank()) { requested = configService.resolveDefaultConfig(preferredConfig, available); } if (requested == null) { HttpResponses.sendJson(exchange, 500, Map.of("error", "No *.json config file found next to the jar")); return; } if (!available.contains(requested)) { Map payload = new LinkedHashMap<>(); payload.put("error", "Unknown config file"); payload.put("files", available); HttpResponses.sendJson(exchange, 400, payload); return; } try { Map doc = configService.assemble(requested); debugState.updateFromConfig(Boolean.TRUE.equals(doc.get("debug")), extractSecrets(doc)); HttpResponses.sendJson(exchange, 200, doc); } catch (Exception e) { HttpResponses.sendJson(exchange, 500, Map.of("error", String.valueOf(e.getMessage()))); } } @SuppressWarnings("unchecked") private static List extractSecrets(Map doc) { List secrets = new ArrayList<>(); collectSecretsFromVariables(doc.get("variables"), secrets); Object groups = doc.get("variableGroups"); if (groups instanceof List groupList) { for (Object g : groupList) { if (g instanceof Map group) { collectSecretsFromVariables(group.get("variables"), secrets); } } } return secrets; } private static void collectSecretsFromVariables(Object variables, List secrets) { if (!(variables instanceof Map varMap)) { return; } for (Object v : varMap.values()) { if (v instanceof Map varDef) { Object isSecret = varDef.get("secret"); Object def = varDef.get("default"); if (Boolean.TRUE.equals(isSecret) && def != null) { secrets.add(String.valueOf(def)); } } } } private static String queryParam(HttpExchange exchange, String name) { String query = exchange.getRequestURI().getRawQuery(); if (query == null) { return null; } for (String pair : query.split("&")) { int eq = pair.indexOf('='); String key = eq >= 0 ? pair.substring(0, eq) : pair; if (!key.equals(name)) { continue; } String value = eq >= 0 ? pair.substring(eq + 1) : ""; try { return URLDecoder.decode(value, StandardCharsets.UTF_8); } catch (Exception e) { return value; } } return null; } }