package cz.trask.adfs.context; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import cz.trask.adfs.config.AppConfig; import cz.trask.adfs.service.AdfsTokenService; public abstract class BaseContextHandler implements HttpHandler { protected final Logger logger = LogManager.getLogger(getClass()); protected static final String METHOD_GET = "GET"; protected static final String METHOD_POST = "POST"; protected static final String CONTENT_TYPE_JSON = "application/json;charset=UTF-8"; protected static final String HEADER_CONTENT_TYPE = "Content-Type"; protected static final String HEADER_CACHE_CONTROL = "Cache-Control"; protected static final String HEADER_PRAGMA = "Pragma"; protected static final String HEADER_EXPIRES = "Expires"; protected static final String HEADER_AUTHORIZATION = "Authorization"; protected static final String VAL_NO_CACHE = "no-cache, no-store, must-revalidate"; protected static final String VAL_PRAGMA_NO_CACHE = "no-cache"; protected static final String VAL_EXPIRES_ZERO = "0"; protected AppConfig appConfig; protected AdfsTokenService tokenService; protected ObjectMapper objectMapper; public void init(AppConfig appConfig, AdfsTokenService tokenService, ObjectMapper objectMapper) { this.appConfig = appConfig; this.tokenService = tokenService; this.objectMapper = objectMapper; } @Override public void handle(HttpExchange exchange) throws IOException { String method = exchange.getRequestMethod(); String path = exchange.getRequestURI().getPath(); logger.debug("Received request: {} {}", method, path); try { processRequest(exchange); } catch (Exception e) { logger.error("Error processing request: {} {}", method, path, e); sendError(exchange, 500, "internal_error", "An unexpected error occurred."); } } protected void processRequest(HttpExchange exchange) throws IOException { String method = exchange.getRequestMethod(); if (METHOD_GET.equalsIgnoreCase(method)) { processRequestGet(exchange); } else if (METHOD_POST.equalsIgnoreCase(method)) { processRequestPost(exchange); } else { sendError(exchange, 405, "method_not_allowed", "Unsupported method: " + method); } } protected void processRequestGet(HttpExchange exchange) throws IOException { sendError(exchange, 405, "method_not_allowed", "GET not supported."); } protected void processRequestPost(HttpExchange exchange) throws IOException { sendError(exchange, 405, "method_not_allowed", "POST not supported."); } protected void sendJson(HttpExchange exchange, int statusCode, Object payload) throws IOException { byte[] responseBytes = objectMapper.writeValueAsBytes(payload); sendResponse(exchange, statusCode, CONTENT_TYPE_JSON, responseBytes); } protected void sendResponse(HttpExchange exchange, int statusCode, String contentType, byte[] body) throws IOException { int length = body != null ? body.length : -1; logger.debug("Sending response: HTTP {} ({} bytes)", statusCode, length); Headers headers = exchange.getResponseHeaders(); if (contentType != null) { headers.set(HEADER_CONTENT_TYPE, contentType); } headers.set(HEADER_CACHE_CONTROL, VAL_NO_CACHE); headers.set(HEADER_PRAGMA, VAL_PRAGMA_NO_CACHE); headers.set(HEADER_EXPIRES, VAL_EXPIRES_ZERO); exchange.sendResponseHeaders(statusCode, length > 0 ? length : 0); if (body != null && body.length > 0) { try (OutputStream outputStream = exchange.getResponseBody()) { outputStream.write(body); } } } protected void sendError(HttpExchange exchange, int statusCode, String error, String errorDescription) throws IOException { logger.debug("Sending error response: HTTP {} - {}: {}", statusCode, error, errorDescription); Map response = new LinkedHashMap<>(); response.put("error", error); response.put("error_description", errorDescription); sendJson(exchange, statusCode, response); } protected String getRequestBody(InputStream requestBody) throws IOException { return new String(requestBody.readAllBytes(), StandardCharsets.UTF_8); } }