From ea12899089289c1d88764c906860d6ffbbde9c7e Mon Sep 17 00:00:00 2001 From: ayushaga14 Date: Fri, 31 Oct 2025 12:39:51 +0530 Subject: [PATCH 1/3] remove tryForCollectionName function --- .../java/com/akto/hybrid_runtime/Main.java | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/apps/mini-runtime/src/main/java/com/akto/hybrid_runtime/Main.java b/apps/mini-runtime/src/main/java/com/akto/hybrid_runtime/Main.java index 819642efd8..c616758fc3 100644 --- a/apps/mini-runtime/src/main/java/com/akto/hybrid_runtime/Main.java +++ b/apps/mini-runtime/src/main/java/com/akto/hybrid_runtime/Main.java @@ -78,38 +78,6 @@ private static void printL(Object o) { static boolean isDashboardInstance = false; - public static boolean tryForCollectionName(String message) { - boolean ret = false; - try { - Gson gson = new Gson(); - - Map json = gson.fromJson(message, Map.class); - - // loggerMaker.info("Json size: " + json.size()); - boolean withoutCidrCond = json.containsKey(GROUP_NAME) && json.containsKey(VXLAN_ID); - boolean withCidrCond = json.containsKey(GROUP_NAME) && json.containsKey(VXLAN_ID) && json.containsKey(VPC_CIDR); - if (withCidrCond || withoutCidrCond) { - ret = true; - String groupName = (String) (json.get(GROUP_NAME)); - String vxlanIdStr = ((Double) json.get(VXLAN_ID)).intValue() + ""; - int vxlanId = Integer.parseInt(vxlanIdStr); - dataActor.updateApiCollectionNameForVxlan(vxlanId, groupName); - - if (json.containsKey(VPC_CIDR)) { - List cidrList = (List) json.get(VPC_CIDR); - loggerMaker.info("cidrList: " + cidrList); - dataActor.updateCidrList(cidrList); - } - } - } catch (Exception e) { - loggerMaker.errorAndAddToDb(e, "error in try collection" + e); - } - - return ret; - } - - - public static void insertRuntimeFilters() { RuntimeFilterDao.instance.initialiseFilters(); } @@ -593,10 +561,6 @@ private static void bulkParseTrafficToResponseParams(long lastSyncOffset, Consum if (DataActor.actualAccountId == 1759692400 && lastSyncOffset % 1000 == 0) { loggerMaker.infoAndAddToDb("Committing offset at position: " + lastSyncOffset); } - - if (DataActor.actualAccountId != 1759692400 && tryForCollectionName(r.value())) { - continue; - } httpResponseParams = HttpCallParser.parseKafkaMessage(r.value()); if (httpResponseParams == null) { From ba63bab37aa043de945b34d55531a4a8a1bb1058 Mon Sep 17 00:00:00 2001 From: ayushaga14 Date: Fri, 31 Oct 2025 13:41:57 +0530 Subject: [PATCH 2/3] remove json parse in buildHeadersMap function --- .../com/akto/dto/OriginalHttpRequest.java | 61 ++++++++++++++++--- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java b/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java index 374686846e..9ca2ffce76 100644 --- a/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java +++ b/libs/dao/src/main/java/com/akto/dto/OriginalHttpRequest.java @@ -3,10 +3,13 @@ import com.akto.dto.testing.TLSAuthParam; import com.akto.dto.type.RequestTemplate; import com.akto.util.HttpRequestResponseUtils; -import com.alibaba.fastjson2.JSON; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; import com.google.gson.Gson; import com.mongodb.BasicDBObject; +import java.io.IOException; import java.util.stream.Collectors; import lombok.Getter; import lombok.Setter; @@ -19,6 +22,7 @@ public class OriginalHttpRequest { private static final Gson gson = new Gson(); + private static final JsonFactory JSON_FACTORY = new JsonFactory(); private String url; private String type; private String queryParams; @@ -242,17 +246,60 @@ public static Map> buildHeadersMap(Map json, String key) { } public static Map> buildHeadersMap(String headersString) { - Map headersFromRequest = JSON.parseObject(headersString); Map> headers = new HashMap<>(); - if (headersFromRequest == null) return headers; - for (Object k: headersFromRequest.keySet()) { - List values = headers.getOrDefault(k,new ArrayList<>()); - values.add(headersFromRequest.get(k).toString()); - headers.put(k.toString().toLowerCase(),values); + if (headersString == null || headersString.isEmpty()) return headers; + + try (JsonParser p = JSON_FACTORY.createParser(headersString)) { + // Expect a single JSON object + if (p.nextToken() != JsonToken.START_OBJECT) return headers; + + String currentKey = null; + while (p.nextToken() != JsonToken.END_OBJECT) { + JsonToken t = p.currentToken(); + + if (t == JsonToken.FIELD_NAME) { + currentKey = p.getCurrentName(); + } else if (currentKey != null) { + // Capture any JSON value as a String + String value = tokenToString(p, t); + String keyLower = currentKey.toLowerCase(); + List values = headers.get(keyLower); + if (values == null) { + values = new ArrayList<>(1); + headers.put(keyLower, values); + } + values.add(value); + currentKey = null; + } + } + } catch (IOException e) { + // Return empty map on parse failure + return new HashMap<>(); } + return headers; } + private static String tokenToString(JsonParser p, JsonToken t) throws IOException { + switch (t) { + case VALUE_STRING: + return p.getValueAsString(); // already unescaped + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + case VALUE_TRUE: + case VALUE_FALSE: + return p.getText(); // numeric or boolean literal text + case VALUE_NULL: + return "null"; + case START_ARRAY: + case START_OBJECT: + // If nested occurs by mistake, read it as compact JSON text + return p.readValueAsTree().toString(); + default: + return p.getText(); // fallback + } + } + public void addHeaderFromLine(String line) { if (this.headers == null || this.headers.isEmpty()) { this.headers = new HashMap<>(); From a3a6d282cda3166f540246cead4ba8ff46d74c15 Mon Sep 17 00:00:00 2001 From: ayushaga14 Date: Fri, 31 Oct 2025 13:46:12 +0530 Subject: [PATCH 3/3] Add uts --- .../akto/dto/TestHeadersMapPerformance.java | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 libs/dao/src/test/java/com/akto/dto/TestHeadersMapPerformance.java diff --git a/libs/dao/src/test/java/com/akto/dto/TestHeadersMapPerformance.java b/libs/dao/src/test/java/com/akto/dto/TestHeadersMapPerformance.java new file mode 100644 index 0000000000..8195ee6f75 --- /dev/null +++ b/libs/dao/src/test/java/com/akto/dto/TestHeadersMapPerformance.java @@ -0,0 +1,174 @@ +package com.akto.dto; + +import org.junit.Test; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + +public class TestHeadersMapPerformance { + + @Test + public void testBuildHeadersMapBasic() { + String headersString = "{\"Content-Type\":\"application/json\",\"Host\":\"example.com\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals(2, headers.size()); + assertEquals("application/json", headers.get("content-type").get(0)); + assertEquals("example.com", headers.get("host").get(0)); + } + + @Test + public void testBuildHeadersMapWithEscapedQuotes() { + String headersString = "{\"accept\":\"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\"accept-encoding\":\"gzip, deflate, br, zstd\",\"accept-language\":\"en-GB,en;q=0.9\",\"cache-control\":\"max-age=0\",\"connection\":\"keep-alive\",\"host\":\"ayush.akto.example\",\"sec-ch-ua\":\"\\\"Not)A;Brand\\\";v=\\\"99\\\", \\\"Google Chrome\\\";v=\\\"127\\\", \\\"Chromium\\\";v=\\\"127\\\"\",\"sec-ch-ua-mobile\":\"?0\",\"sec-ch-ua-platform\":\"\\\"macOS\\\"\",\"sec-fetch-dest\":\"document\",\"sec-fetch-mode\":\"navigate\",\"sec-fetch-site\":\"none\",\"sec-fetch-user\":\"?1\",\"upgrade-insecure-requests\":\"1\",\"user-agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36\"}"; + + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertTrue(headers.size() > 10); + assertEquals("ayush.akto.example", headers.get("host").get(0)); + assertEquals("\"Not)A;Brand\";v=\"99\", \"Google Chrome\";v=\"127\", \"Chromium\";v=\"127\"", headers.get("sec-ch-ua").get(0)); + assertEquals("\"macOS\"", headers.get("sec-ch-ua-platform").get(0)); + } + + @Test + public void testBuildHeadersMapEmpty() { + Map> headers1 = OriginalHttpRequest.buildHeadersMap(""); + Map> headers2 = OriginalHttpRequest.buildHeadersMap(null); + Map> headers3 = OriginalHttpRequest.buildHeadersMap("{}"); + + assertNotNull(headers1); + assertTrue(headers1.isEmpty()); + assertNotNull(headers2); + assertTrue(headers2.isEmpty()); + assertNotNull(headers3); + assertTrue(headers3.isEmpty()); + } + + @Test + public void testBuildHeadersMapCaseInsensitive() { + String headersString = "{\"Content-Type\":\"application/json\",\"HOST\":\"example.com\",\"Accept\":\"*/*\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("application/json", headers.get("content-type").get(0)); + assertEquals("example.com", headers.get("host").get(0)); + assertEquals("*/*", headers.get("accept").get(0)); + } + + @Test + public void testBuildHeadersMapWithUnicodeAndSpecialChars() { + String headersString = "{\"X-Custom-Header\":\"Hello δΈ–η•Œ 🌍\",\"Content-Type\":\"text/plain; charset=utf-8\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("Hello δΈ–η•Œ 🌍", headers.get("x-custom-header").get(0)); + assertEquals("text/plain; charset=utf-8", headers.get("content-type").get(0)); + } + + @Test + public void testBuildHeadersMapWithBackslashes() { + String headersString = "{\"X-Path\":\"C:\\\\Users\\\\test\\\\file.txt\",\"X-Regex\":\"\\\\d+\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("C:\\Users\\test\\file.txt", headers.get("x-path").get(0)); + assertEquals("\\d+", headers.get("x-regex").get(0)); + } + + @Test + public void testBuildHeadersMapWithNewlinesAndTabs() { + String headersString = "{\"X-Multiline\":\"Line1\\nLine2\\nLine3\",\"X-Tab\":\"Col1\\tCol2\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("Line1\nLine2\nLine3", headers.get("x-multiline").get(0)); + assertEquals("Col1\tCol2", headers.get("x-tab").get(0)); + } + + @Test + public void testBuildHeadersMapWithEmptyValues() { + String headersString = "{\"Empty\":\"\",\"Host\":\"example.com\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("", headers.get("empty").get(0)); + assertEquals("example.com", headers.get("host").get(0)); + } + + @Test + public void testBuildHeadersMapWithNumericValues() { + String headersString = "{\"Content-Length\":12345,\"X-Rate-Limit\":100,\"X-Float\":3.14}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("12345", headers.get("content-length").get(0)); + assertEquals("100", headers.get("x-rate-limit").get(0)); + assertEquals("3.14", headers.get("x-float").get(0)); + } + + @Test + public void testBuildHeadersMapWithBooleanAndNull() { + String headersString = "{\"X-Enabled\":true,\"X-Disabled\":false,\"X-Null\":null}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("true", headers.get("x-enabled").get(0)); + assertEquals("false", headers.get("x-disabled").get(0)); + assertEquals("null", headers.get("x-null").get(0)); + } + + @Test + public void testBuildHeadersMapWithJsonInValue() { + // Edge case: nested JSON as a string value + String headersString = "{\"X-Json-Data\":\"{\\\"key\\\":\\\"value\\\"}\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("{\"key\":\"value\"}", headers.get("x-json-data").get(0)); + } + + @Test + public void testBuildHeadersMapWithWhitespace() { + String headersString = "{ \"Host\" : \"example.com\" , \"Content-Type\" : \"application/json\" }"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("example.com", headers.get("host").get(0)); + assertEquals("application/json", headers.get("content-type").get(0)); + } + + @Test + public void testBuildHeadersMapWithInvalidJson() { + String headersString = "{\"Host\":\"example.com\" INVALID"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + // Should return empty map on parse failure + assertNotNull(headers); + assertTrue(headers.isEmpty()); + } + + @Test + public void testBuildHeadersMapDuplicateKeys() { + // NOTE: In standard JSON, duplicate keys are not allowed, but if they occur, + // the last value typically wins. However, our implementation should handle this gracefully. + // Jackson will only see the last occurrence in the JSON string. + String headersString = "{\"Cookie\":\"session=abc\",\"Cookie\":\"user=123\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + // Jackson will parse and we'll see only one entry (the last one typically) + assertTrue(headers.containsKey("cookie")); + } + + @Test + public void testBuildHeadersMapWithForwardSlashesAndUrls() { + String headersString = "{\"Referer\":\"https://example.com/path/to/page?query=value\",\"X-Forwarded-For\":\"192.168.1.1, 10.0.0.1\"}"; + Map> headers = OriginalHttpRequest.buildHeadersMap(headersString); + + assertNotNull(headers); + assertEquals("https://example.com/path/to/page?query=value", headers.get("referer").get(0)); + assertEquals("192.168.1.1, 10.0.0.1", headers.get("x-forwarded-for").get(0)); + } +}