diff --git a/src/main/java/com/uid2/shared/util/HTTPPathMetricFilter.java b/src/main/java/com/uid2/shared/util/HTTPPathMetricFilter.java new file mode 100644 index 00000000..4e403de8 --- /dev/null +++ b/src/main/java/com/uid2/shared/util/HTTPPathMetricFilter.java @@ -0,0 +1,19 @@ +package com.uid2.shared.util; + +import io.vertx.core.http.impl.HttpUtils; +import java.util.Set; + +public class HTTPPathMetricFilter { + public static String filterPath(String actualPath, Set pathSet) { + try { + String normalized = HttpUtils.normalizePath(actualPath).split("\\?")[0]; + if (normalized.charAt(normalized.length() - 1) == '/') { + normalized = normalized.substring(0, normalized.length() - 1); + } + normalized = normalized.toLowerCase(); + return pathSet == null || pathSet.isEmpty() || pathSet.contains(normalized) ? normalized : "/unknown"; + } catch (IllegalArgumentException e) { + return "/parsing_error"; + } + } +} diff --git a/src/test/java/com/uid2/shared/util/HTTPPathMetricFilterTest.java b/src/test/java/com/uid2/shared/util/HTTPPathMetricFilterTest.java new file mode 100644 index 00000000..85ea092b --- /dev/null +++ b/src/test/java/com/uid2/shared/util/HTTPPathMetricFilterTest.java @@ -0,0 +1,53 @@ +package com.uid2.shared.util; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HTTPPathMetricFilterTest { + final Set pathSet = Set.of("/v1/identity/map", "/token/refresh"); + + @ParameterizedTest + @ValueSource(strings = { + "", + "/", + "/unknown-path", + "../", + "/v1/identity/map%55", + }) + void testPathFiltering_InvalidPaths_Unknown(String actualPath) { + String filteredPath = HTTPPathMetricFilter.filterPath(actualPath, pathSet); + assertEquals("/unknown", filteredPath); + } + + @ParameterizedTest + @ValueSource(strings = { + "v1/identity/map?id=bad-escape-code%2", + "token/refresh?refresh_token=SOME_TOKEN<%=7485*4353%>", + }) + void testPathFiltering_InvalidPaths_ParsingError(String actualPath) { + String filteredPath = HTTPPathMetricFilter.filterPath(actualPath, pathSet); + assertEquals("/parsing_error", filteredPath); + } + + @ParameterizedTest + @CsvSource(value = { + "/v1/identity/map, /v1/identity/map", + "v1/identity/map, /v1/identity/map", + "V1/IdenTity/mAp, /v1/identity/map", + "./v1//identity//map/, /v1/identity/map", + "../v1/identity/./map, /v1/identity/map", + "/v1/identity/new/path/../../map, /v1/identity/map", + "token/refresh?refresh_token=123%20%23, /token/refresh", + "v1/identity/map?identity/../map/, /v1/identity/map", + + }) + void testPathFiltering_ValidPaths_KnownEndpoints(String actualPath, String expectedFilteredPath) { + String filteredPath = HTTPPathMetricFilter.filterPath(actualPath, pathSet); + assertEquals(expectedFilteredPath, filteredPath); + } +}