diff --git a/src/main/java/org/example/ConnectionHandler.java b/src/main/java/org/example/ConnectionHandler.java index 1fcc29fb..d98475a0 100644 --- a/src/main/java/org/example/ConnectionHandler.java +++ b/src/main/java/org/example/ConnectionHandler.java @@ -4,8 +4,12 @@ import org.example.filter.IpFilter; import org.example.httpparser.HttpParser; import org.example.httpparser.HttpRequest; + import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + import org.example.filter.Filter; import org.example.filter.FilterChainImpl; import org.example.http.HttpResponseBuilder; @@ -13,6 +17,8 @@ import java.io.IOException; import java.net.Socket; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; public class ConnectionHandler implements AutoCloseable { @@ -40,7 +46,6 @@ private List buildFilters() { if (Boolean.TRUE.equals(ipFilterConfig.enabled())) { list.add(createIpFilterFromConfig(ipFilterConfig)); } - // Add more filters here... return list; } @@ -58,12 +63,18 @@ public void runConnectionHandler() throws IOException { parser.parseRequest(); parser.parseHttp(); + // --- ISSUE FIX --- + String rawUri = parser.getUri(); + String pathOnly = extractPath(rawUri); + Map> queryParams = parseQueryParams(rawUri); + HttpRequest request = new HttpRequest( parser.getMethod(), - parser.getUri(), + pathOnly, parser.getVersion(), parser.getHeadersMap(), - "" + "", + queryParams ); String clientIp = client.getInetAddress().getHostAddress(); @@ -80,16 +91,14 @@ public void runConnectionHandler() throws IOException { return; } - resolveTargetFile(parser.getUri()); + resolveTargetFile(request.getPath()); sfh.sendGetRequest(client.getOutputStream(), uri); } private HttpResponseBuilder applyFilters(HttpRequest request) { HttpResponseBuilder response = new HttpResponseBuilder(); - FilterChainImpl chain = new FilterChainImpl(filters); chain.doFilter(request, response); - return response; } @@ -101,6 +110,67 @@ private void resolveTargetFile(String uri) { } } + // ----------------------------- + // Query parsing without split() + // ----------------------------- + + private static String extractPath(String uri) { + if (uri == null || uri.isEmpty()) return "/"; + int q = uri.indexOf('?'); + String path = (q >= 0) ? uri.substring(0, q) : uri; + return path.isEmpty() ? "/" : path; + } + + private static Map> parseQueryParams(String uri) { + Map> params = new HashMap<>(); + if (uri == null) return params; + + int questionMarkIndex = uri.indexOf('?'); + if (questionMarkIndex < 0 || questionMarkIndex == uri.length() - 1) { + return params; + } + + String query = uri.substring(questionMarkIndex + 1); + + int start = 0; + while (start < query.length()) { + + int ampIndex = query.indexOf('&', start); + if (ampIndex == -1) { + ampIndex = query.length(); + } + + String pair = query.substring(start, ampIndex); + + int equalsIndex = pair.indexOf('='); + + if (pair.isEmpty()) { + start = ampIndex + 1; + continue; + } + + String key; + String value; + + if (equalsIndex >= 0) { + key = pair.substring(0, equalsIndex); + value = pair.substring(equalsIndex + 1); + } else { + key = pair; + value = ""; + } + + key = URLDecoder.decode(key, StandardCharsets.UTF_8); + value = URLDecoder.decode(value, StandardCharsets.UTF_8); + + params.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + + start = ampIndex + 1; + } + + return params; + } + @Override public void close() throws Exception { client.close(); @@ -109,19 +179,16 @@ public void close() throws Exception { private IpFilter createIpFilterFromConfig(AppConfig.IpFilterConfig config) { IpFilter filter = new IpFilter(); - // Set mode if ("ALLOWLIST".equalsIgnoreCase(config.mode())) { filter.setMode(IpFilter.FilterMode.ALLOWLIST); } else { filter.setMode(IpFilter.FilterMode.BLOCKLIST); } - // Add blocked IPs for (String ip : config.blockedIps()) { filter.addBlockedIp(ip); } - // Add allowed IPs for (String ip : config.allowedIps()) { filter.addAllowedIp(ip); } diff --git a/src/main/java/org/example/httpparser/HttpRequest.java b/src/main/java/org/example/httpparser/HttpRequest.java index 18f0e561..3c328107 100644 --- a/src/main/java/org/example/httpparser/HttpRequest.java +++ b/src/main/java/org/example/httpparser/HttpRequest.java @@ -2,48 +2,82 @@ import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; /* -* -*This class groups together all information about a request that the server needs + * + * This class groups together all information about a request that the server needs */ public class HttpRequest { - private final String method; - private final String path; - private final String version; - private final Map headers; - private final String body; - private final Map attributes = new HashMap<>(); - - public HttpRequest(String method, - String path, - String version, - Map headers, - String body) { - this.method = method; - this.path = path; - this.version = version; - this.headers = headers != null ? Map.copyOf(headers) : Collections.emptyMap(); - this.body = body; - } - - public String getMethod() { - return method; } - public String getPath() { - return path; } - public String getVersion() { - return version; } - public Map getHeaders() { - return headers; } - public String getBody() { - return body; } - public void setAttribute(String key, Object value) { - attributes.put(key, value); - } - public Object getAttribute(String key) { - return attributes.get(key); - } + private final String method; + private final String path; + private final String version; + private final Map headers; + private final String body; + + private final Map> queryParams; + + private final Map attributes = new HashMap<>(); + + public HttpRequest(String method, + String path, + String version, + Map headers, + String body) { + this(method, path, version, headers, body, Collections.emptyMap()); + } + + public HttpRequest(String method, + String path, + String version, + Map headers, + String body, + Map> queryParams) { + + this.method = method; + this.path = path; + this.version = version; + this.headers = headers != null ? Map.copyOf(headers) : Collections.emptyMap(); + this.body = body; + this.queryParams = queryParams != null ? Map.copyOf(queryParams) : Collections.emptyMap(); + } + + public String getMethod() { + return method; + } + + public String getPath() { + return path; + } + + public String getVersion() { + return version; + } + + public Map getHeaders() { + return headers; + } + + public String getBody() { + return body; + } + + public Map> getQueryParams() { + return queryParams; + } + + public List getQueryParam(String key) { + return queryParams.getOrDefault(key, List.of()); + } + + public void setAttribute(String key, Object value) { + attributes.put(key, value); + } + + public Object getAttribute(String key) { + return attributes.get(key); } +} \ No newline at end of file