From 43d1b3b49eb7fe6957fb75e7d1e9e576e6b401ad Mon Sep 17 00:00:00 2001 From: brharrington Date: Thu, 22 Jun 2023 10:34:27 -0500 Subject: [PATCH] support allow set for PathSanitizer (#1065) This allows an explicit set of allowed segment strings for some use-cases where there is a small set of known strings that are desirable to include, but do not match with the normal rules. --- .../spectator/ipc/http/PathSanitizer.java | 30 +++++++++++++++---- .../spectator/ipc/http/PathSanitizerTest.java | 14 ++++++++- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/http/PathSanitizer.java b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/http/PathSanitizer.java index 723de7adb..50cdac5c1 100644 --- a/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/http/PathSanitizer.java +++ b/spectator-ext-ipc/src/main/java/com/netflix/spectator/ipc/http/PathSanitizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2021 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,9 @@ import com.netflix.spectator.impl.AsciiSet; +import java.util.Collections; +import java.util.Set; + /** * Helper for sanitizing a URL path for including as the {@code ipc.endpoint} value. Makes * a best effort to try and remove segments that tend to be variable like numbers, UUIDs, @@ -37,7 +40,22 @@ private PathSanitizer() { /** Returns a sanitized path string for use as an endpoint tag value. */ public static String sanitize(String path) { - return sanitizeSegments(removeParameters(path)); + return sanitizeSegments(removeParameters(path), Collections.emptySet()); + } + + /** + * Returns a sanitized path string for use as an endpoint tag value. + * + * @param path + * Path from a URI that should be sanitized. + * @param allowed + * Set of allowed segment strings. This can be used to override the default rules for + * a set of known good values. + * @return + * Sanitized path that can be used as an endpoint tag value. + */ + public static String sanitize(String path, Set allowed) { + return sanitizeSegments(removeParameters(path), allowed); } private static String removeParameters(String path) { @@ -49,7 +67,7 @@ private static String removeParameters(String path, char c) { return i > 0 ? path.substring(0, i) : path; } - private static String sanitizeSegments(String path) { + private static String sanitizeSegments(String path, Set allowed) { StringBuilder builder = new StringBuilder(); int length = path.length(); int pos = path.charAt(0) == '/' ? 1 : 0; @@ -67,7 +85,7 @@ private static String sanitizeSegments(String path) { } if (!segment.isEmpty()) { - if (shouldSuppressSegment(segment)) + if (shouldSuppressSegment(segment, allowed)) appendIfSpaceAvailable(builder, "-"); else appendIfSpaceAvailable(builder, segment); @@ -78,10 +96,10 @@ private static String sanitizeSegments(String path) { return builder.toString(); } - private static boolean shouldSuppressSegment(String segment) { + private static boolean shouldSuppressSegment(String segment, Set allowed) { // GraphQL is a common endpoint, but hits the consonants check to detect strings // that are likely to be random. Special case it for now. - if ("graphql".equals(segment)) { + if ("graphql".equals(segment) || allowed.contains(segment)) { return false; } diff --git a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/http/PathSanitizerTest.java b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/http/PathSanitizerTest.java index bc3bbcf16..faf704262 100644 --- a/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/http/PathSanitizerTest.java +++ b/spectator-ext-ipc/src/test/java/com/netflix/spectator/ipc/http/PathSanitizerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2021 Netflix, Inc. + * Copyright 2014-2023 Netflix, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Random; +import java.util.Set; import java.util.UUID; public class PathSanitizerTest { @@ -107,6 +109,16 @@ public void graphql() { Assertions.assertEquals("_graphql", sanitize(path)); } + @Test + public void allowSet() { + String path = "/foo-bar"; + Assertions.assertEquals("_-", PathSanitizer.sanitize(path)); + + Set allowed = Collections.singleton("foo-bar"); + Assertions.assertEquals("_foo-bar", PathSanitizer.sanitize(path, allowed)); + Assertions.assertEquals("_api_v1_foo-bar", PathSanitizer.sanitize("/api/v1" + path, allowed)); + } + @Test public void randomLookingString() { String path = "/random/AOTV16LMT2";