Browse Source

Introduce queryParamPredicate in AbstractRequestLoggingFilter

Closes gh-35603

Signed-off-by: Simone Conte <conte@adobe.com>
pull/35608/head
Simone Conte 4 months ago committed by Sam Brannen
parent
commit
87a7507e3a
  1. 47
      spring-web/src/main/java/org/springframework/web/filter/AbstractRequestLoggingFilter.java
  2. 7
      spring-web/src/test/java/org/springframework/web/filter/RequestLoggingFilterTests.java

47
spring-web/src/main/java/org/springframework/web/filter/AbstractRequestLoggingFilter.java

@ -31,8 +31,11 @@ import org.jspecify.annotations.Nullable; @@ -31,8 +31,11 @@ import org.jspecify.annotations.Nullable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.WebUtils;
/**
@ -99,6 +102,8 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter @@ -99,6 +102,8 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
private boolean includePayload = false;
private @Nullable Predicate<String> queryParamPredicate;
private @Nullable Predicate<String> headerPredicate;
private int maxPayloadLength = DEFAULT_MAX_PAYLOAD_LENGTH;
@ -182,6 +187,30 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter @@ -182,6 +187,30 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
return this.includePayload;
}
/**
* Configure a predicate for selecting which query params should be logged if
* {@link #setIncludeQueryString(boolean)} is set to {@code true}.
* <p>By default this is not set in which case all query params are logged
*
* <p>If there are multiple values for the same query param,
* the predicate will be applied once per query param name.
* As a result, the use of this predicate may result in a different query string
* than the one returned by {@link HttpServletRequest#getQueryString()}.
* @param queryParamPredicate the predicate to use
* @since 7.0
*/
public void setQueryParamPredicate(@Nullable Predicate<String> queryParamPredicate) {
this.queryParamPredicate = queryParamPredicate;
}
/**
* The configured {@link #setQueryParamPredicate(Predicate) queryParamPredicate}.
* @since 7.0
*/
protected @Nullable Predicate<String> getQueryParamPredicate() {
return this.queryParamPredicate;
}
/**
* Configure a predicate for selecting which headers should be logged if
* {@link #setIncludeHeaders(boolean)} is set to {@code true}.
@ -326,6 +355,24 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter @@ -326,6 +355,24 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
if (isIncludeQueryString()) {
String queryString = request.getQueryString();
if (queryString != null) {
if (getQueryParamPredicate() != null) {
MultiValueMap<String, String> queryParams = UriComponentsBuilder.fromUriString("?" + queryString)
.build()
.getQueryParams();
MultiValueMap<String, String> updatedQueryParams = new LinkedMultiValueMap<>(queryParams);
for (String name : queryParams.keySet()) {
if (!getQueryParamPredicate().test(name)) {
updatedQueryParams.set(name, "masked");
break;
}
}
queryString = UriComponentsBuilder.newInstance()
.queryParams(updatedQueryParams)
.build()
.getQuery();
}
msg.append('?').append(queryString);
}
}

7
spring-web/src/test/java/org/springframework/web/filter/RequestLoggingFilterTests.java

@ -108,13 +108,14 @@ class RequestLoggingFilterTests { @@ -108,13 +108,14 @@ class RequestLoggingFilterTests {
@Test
void queryStringIncluded() throws Exception {
request.setQueryString("booking=42");
request.setQueryString("booking=42&code=73&category=hotel&code=37&category=resort");
filter.setIncludeQueryString(true);
filter.setQueryParamPredicate(name -> !name.equals("code") && !name.equals("ignore"));
applyFilter();
assertThat(filter.beforeRequestMessage).contains("/hotels?booking=42");
assertThat(filter.afterRequestMessage).contains("/hotels?booking=42");
assertThat(filter.beforeRequestMessage).contains("/hotels?booking=42&code=masked&category=hotel&category=resort");
assertThat(filter.afterRequestMessage).contains("/hotels?booking=42&code=masked&category=hotel&category=resort");
}
@Test

Loading…
Cancel
Save