@@ -36,6 +36,11 @@ public final class Censors {
3636 */
3737 private final List <CensorElement > queryParamsToCensor ;
3838
39+ /**
40+ * The URL path elements to censor.
41+ */
42+ private final List <RegexCensorElement > pathElementsToCensor ;
43+
3944 /**
4045 * Initialize a new instance of the Censors factory, using default censor string.
4146 */
@@ -52,6 +57,7 @@ public Censors(String censorString) {
5257 this .queryParamsToCensor = new ArrayList <>();
5358 this .bodyElementsToCensor = new ArrayList <>();
5459 this .headersToCensor = new ArrayList <>();
60+ this .pathElementsToCensor = new ArrayList <>();
5561 this .censorText = censorString ;
5662 }
5763
@@ -126,7 +132,7 @@ private static List<Object> applyJsonCensors(List<Object> list, String censorTex
126132 * @param dictionary JSON dictionary to process.
127133 * @param censorText Text to use when censoring an element.
128134 * @param elementsToCensor List of elements to find and censor.
129- * @return Censored JSON dicstionary .
135+ * @return Censored JSON dictionary .
130136 */
131137 private static Map <String , Object > applyJsonCensors (Map <String , Object > dictionary , String censorText ,
132138 List <CensorElement > elementsToCensor ) {
@@ -280,45 +286,73 @@ public static Map<String, List<String>> applyHeaderCensors(Map<String, List<Stri
280286 /**
281287 * Censor the appropriate query parameters.
282288 *
283- * @param url Full URL string to apply censors to.
284- * @param censorText The string to use to censor sensitive information.
285- * @param queryParamsToCensor The query parameters to censor.
289+ * @param url Full URL string to apply censors to.
290+ * @param censorText The string to use to censor sensitive information.
291+ * @param queryParamsToCensor The query parameters to censor.
292+ * @param pathElementsToCensor The path elements to censor.
286293 * @return Censored URL string.
287294 */
288- public static String applyQueryParameterCensors (String url , String censorText ,
289- List <CensorElement > queryParamsToCensor ) {
295+ public static String applyUrlCensors (String url , String censorText ,
296+ List <CensorElement > queryParamsToCensor ,
297+ List <RegexCensorElement > pathElementsToCensor ) {
290298 if (url == null || url .length () == 0 ) {
291299 // short circuit if url is null
292300 return url ;
293301 }
294302
295- if (queryParamsToCensor .size () == 0 ) {
303+ if (queryParamsToCensor .size () == 0 && pathElementsToCensor . size () == 0 ) {
296304 // short circuit if there are no censors to apply
297305 return url ;
298306 }
299307
300308 URI uri = URI .create (url );
301- Map <String , String > queryParameters = Tools .queryParametersToMap (uri );
309+
310+ String path = Utilities .extractPathFromUri (uri );
311+ Map <String , String > queryParameters = Utilities .queryParametersToMap (uri );
312+
313+ String censoredPath ;
314+ String censoredQueryString ;
315+
316+ if (pathElementsToCensor .size () == 0 ) {
317+ // don't need to censor path elements
318+ censoredPath = path ;
319+ } else {
320+ // censor path elements
321+ String tempPath = path ;
322+ for (RegexCensorElement regexCensorElement : pathElementsToCensor ) {
323+ tempPath = regexCensorElement .matchAndReplaceAsNeeded (tempPath , censorText );
324+ }
325+
326+ censoredPath = tempPath ;
327+ }
328+
302329 if (queryParameters .size () == 0 ) {
303330 // short circuit if there are no query parameters to censor
304- return url ;
305- }
331+ censoredQueryString = null ;
332+ } else {
333+ if (queryParamsToCensor .size () == 0 ) {
334+ // don't need to censor query parameters
335+ censoredQueryString = uri .getQuery ();
336+ } else {
337+ // censor query parameters
338+ List <String > queryKeys = new ArrayList <>(queryParameters .keySet ());
339+ for (String queryKey : queryKeys ) {
340+ if (elementShouldBeCensored (queryKey , queryParamsToCensor )) {
341+ queryParameters .put (queryKey , censorText );
342+ }
343+ }
306344
307- List <String > queryKeys = new ArrayList <>(queryParameters .keySet ());
308- for (String queryKey : queryKeys ) {
309- if (elementShouldBeCensored (queryKey , queryParamsToCensor )) {
310- queryParameters .put (queryKey , censorText );
345+ List <NameValuePair > censoredQueryParametersList = Tools .mapToQueryParameters (queryParameters );
346+ censoredQueryString = URLEncodedUtils .format (censoredQueryParametersList , StandardCharsets .UTF_8 );
311347 }
312348 }
313349
314- List <NameValuePair > censoredQueryParametersList = Tools .mapToQueryParameters (queryParameters );
315- String formattedQueryParameters = URLEncodedUtils .format (censoredQueryParametersList , StandardCharsets .UTF_8 );
316- if (formattedQueryParameters .length () == 0 ) {
317- // short circuit if there are no query parameters to censor
318- return url ;
350+ String censoredUrl = censoredPath ;
351+ if (censoredQueryString != null ) {
352+ censoredUrl += "?" + censoredQueryString ;
319353 }
320354
321- return uri .getScheme () + "://" + uri . getHost () + uri . getPath () + "?" + formattedQueryParameters ;
355+ return uri .getScheme () + "://" + censoredUrl ;
322356 }
323357
324358 /**
@@ -360,7 +394,7 @@ public Censors censorBodyElementsByKeys(List<String> elementKeys) {
360394 * Add a rule to censor specified headers.
361395 * Note: This will censor the header keys in both the request and response.
362396 *
363- * @param headers List of Headers to censor.
397+ * @param headers List of headers to censor.
364398 * @return This Censors factory.
365399 */
366400 public Censors censorHeaders (List <CensorElement > headers ) {
@@ -397,7 +431,7 @@ public Censors censorHeadersByKeys(List<String> headerKeys) {
397431 /**
398432 * Add a rule to censor specified query parameters.
399433 *
400- * @param elements List of QueryElements to censor.
434+ * @param elements List of query parameters to censor.
401435 * @return This Censors factory.
402436 */
403437 public Censors censorQueryParameters (List <CensorElement > elements ) {
@@ -429,6 +463,41 @@ public Censors censorQueryParametersByKeys(List<String> parameterKeys) {
429463 return censorQueryParametersByKeys (parameterKeys , false );
430464 }
431465
466+ /**
467+ * Add a rule to censor specified path elements.
468+ *
469+ * @param elements List of path elements to censor.
470+ * @return This Censors factory.
471+ */
472+ public Censors censorPathElements (List <RegexCensorElement > elements ) {
473+ pathElementsToCensor .addAll (elements );
474+ return this ;
475+ }
476+
477+ /**
478+ * Add a rule to censor specified path elements by regular expression patterns.
479+ *
480+ * @param patterns Patterns of path elements to censor.
481+ * @param caseSensitive Whether to use case-sensitive pattern matching.
482+ * @return This Censors factory.
483+ */
484+ public Censors censorPathElementsByPattern (List <String > patterns , boolean caseSensitive ) {
485+ for (String pattern : patterns ) {
486+ pathElementsToCensor .add (new RegexCensorElement (pattern , caseSensitive ));
487+ }
488+ return this ;
489+ }
490+
491+ /**
492+ * Add a rule to censor specified path elements by regular expression patterns.
493+ *
494+ * @param patterns Patterns of path elements to censor.
495+ * @return This Censors factory.
496+ */
497+ public Censors censorPathElementsByPattern (List <String > patterns ) {
498+ return censorPathElementsByPattern (patterns , false );
499+ }
500+
432501 /**
433502 * Censor the appropriate body elements.
434503 *
@@ -455,7 +524,7 @@ public Map<String, List<String>> applyHeaderCensors(Map<String, List<String>> he
455524 * @param url Full URL string to apply censors to.
456525 * @return Censored URL string.
457526 */
458- public String applyQueryParameterCensors (String url ) {
459- return applyQueryParameterCensors (url , this .censorText , this .queryParamsToCensor );
527+ public String applyUrlCensors (String url ) {
528+ return applyUrlCensors (url , this .censorText , this .queryParamsToCensor , this . pathElementsToCensor );
460529 }
461530}
0 commit comments