From 62a667887bec7822ff5ffd8ae51dd254aae91a32 Mon Sep 17 00:00:00 2001 From: almeidast Date: Tue, 19 Nov 2024 14:51:40 +0100 Subject: [PATCH] Introduced a regular expression (Regex) cache to avoid redundant recompilation. Updated filter processing to utilize precompiled Pattern objects for improved performance. Implemented methods to reuse regular expressions using computeIfAbsent. Modified the filterProperty method to accept and work with precompiled regular expressions (Pattern). Updated to reflect changes in the RequestPropertyFilter class, adapting tests to use Pattern instead of strings for regular expressions. --- .../gateleen/logging/LoggingHandler.java | 188 +++++------------- .../logging/RequestPropertyFilter.java | 38 ++-- .../logging/RequestPropertyFilterTest.java | 85 ++++---- 3 files changed, 117 insertions(+), 194 deletions(-) diff --git a/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/LoggingHandler.java b/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/LoggingHandler.java index 094d9322d..2951dc2c2 100755 --- a/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/LoggingHandler.java +++ b/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/LoggingHandler.java @@ -12,10 +12,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.appender.RollingFileAppender; -import org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy; import org.apache.logging.log4j.core.layout.PatternLayout; import org.slf4j.Logger; -import org.swisspush.gateleen.core.event.EventBusWriter; import org.swisspush.gateleen.core.http.RequestLoggerFactory; import java.util.ArrayList; @@ -23,22 +21,24 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.regex.Pattern; /** + * Updated LoggingHandler with regex caching + * * @author https://github.com/mcweba [Marc-Andre Weber] */ public class LoggingHandler { - private HttpServerRequest request; + private final HttpServerRequest request; private MultiMap requestHeaders; private HttpClientResponse response; private boolean active = false; private Buffer requestPayload; private Buffer responsePayload; - private LoggingResource loggingResource; - private EventBus eventBus; - private LogAppenderRepository logAppenderRepository; + private final LoggingResource loggingResource; + private final LogAppenderRepository logAppenderRepository; private String currentDestination; @@ -49,9 +49,7 @@ public class LoggingHandler { private static final String DEFAULT_LOGGER = "RequestLog"; private static final String REJECT = "reject"; private static final String DESTINATION = "destination"; - private static final String DESCRIPTION = "description"; - private static final String META_DATA = "metadata"; - private static final String TRANSMISSION = "transmission"; + private static final String URL = "url"; private static final String METHOD = "method"; private static final String STATUS_CODE = "statusCode"; @@ -60,39 +58,43 @@ public class LoggingHandler { private static final String RESPONSE = "response"; private static final String HEADERS = "headers"; private static final String BODY = "body"; - private static final String FILE = "file"; - private static final String ADDRESS = "address"; - private static final String DEFAULT = "default"; public static final String SKIP_LOGGING_HEADER = "x-skip-request-log"; - private Map loggers = new HashMap<>(); + private final Map loggers = new HashMap<>(); + private final Logger log; + + // Cache for precompiled regex patterns + private static final Map regexCache = new HashMap<>(); - private Logger log; + // Helper method to fetch or compile a regex pattern + private static Pattern getOrCompilePattern(String regex) { + return regexCache.computeIfAbsent(regex, Pattern::compile); + } public LoggingHandler(LoggingResourceManager loggingResourceManager, LogAppenderRepository logAppenderRepository, HttpServerRequest request, EventBus eventBus) { this.logAppenderRepository = logAppenderRepository; this.request = request; - this.eventBus = eventBus; this.loggingResource = loggingResourceManager.getLoggingResource(); this.log = RequestLoggerFactory.getLogger(LoggingHandler.class, request); ((org.apache.logging.log4j.core.Logger) LogManager.getLogger(DEFAULT_LOGGER)).setAdditive(false); - boolean stopValidation = false; - if(request.headers().get(SKIP_LOGGING_HEADER) != null) { - log.info("request will not be logged because of skip log request header"); + if (request.headers().get(SKIP_LOGGING_HEADER) != null) { + log.info("Request will not be logged because of skip log request header"); return; } + boolean stopValidation = false; + for (Map payloadFilter : loggingResource.getPayloadFilters()) { if (active || stopValidation) { break; } - // NEMO-5551: Custom sorting. We have to make sure key "URL" comes first in the array. + // Sort "url" key to the head of the list List> payloadFilterEntrySetList = new ArrayList<>(); for (Entry filterEntry : payloadFilter.entrySet()) { - if (filterEntry.getKey().equalsIgnoreCase("url")) { + if (filterEntry.getKey().equalsIgnoreCase(URL)) { payloadFilterEntrySetList.add(0, filterEntry); } else { payloadFilterEntrySetList.add(filterEntry); @@ -101,23 +103,17 @@ public LoggingHandler(LoggingResourceManager loggingResourceManager, LogAppender boolean reject = Boolean.parseBoolean(payloadFilter.get(REJECT)); for (Entry filterEntry : payloadFilterEntrySetList) { - if (REJECT.equalsIgnoreCase(filterEntry.getKey()) - || DESTINATION.equalsIgnoreCase(filterEntry.getKey()) - || DESCRIPTION.equalsIgnoreCase(filterEntry.getKey())) { - continue; - } + String key = filterEntry.getKey(); + String value = filterEntry.getValue(); + Pattern pattern = getOrCompilePattern(value); - FilterResult result = RequestPropertyFilter.filterProperty(request, filterEntry.getKey(), filterEntry.getValue(), reject); - if (result == FilterResult.FILTER) { + if (RequestPropertyFilter.filterProperty(request, key, pattern, reject) == FilterResult.FILTER) { active = true; currentDestination = createLoggerAndGetDestination(payloadFilter); - } else if (result == FilterResult.REJECT) { + } else if (RequestPropertyFilter.filterProperty(request, key, pattern, reject) == FilterResult.REJECT) { active = false; stopValidation = true; break; - } else if (result == FilterResult.NO_MATCH) { - active = false; - break; } } } @@ -127,134 +123,46 @@ public boolean isActive() { return this.active; } - /** - * Returns the destination key for the given filterProperty. If no destination is - * set the default key is used instead.
- * A logger for the given destination is created if necessary or reused if - * it already exists. - * - * @param payloadFilter - * @return currentDestination - */ private String createLoggerAndGetDestination(Map payloadFilter) { - // the destination of the active filterProperty String filterDestination = payloadFilter.get(DESTINATION); - - // if not available set to 'default' if (filterDestination == null) { - log.debug("no filterDestination set"); - filterDestination = DEFAULT; + log.debug("No filterDestination set"); + filterDestination = DEFAULT_LOGGER; } - // if the key is found, create a logger for the given file ... if (loggingResource.getDestinationEntries().containsKey(filterDestination)) { Map destinationOptions = loggingResource.getDestinationEntries().get(filterDestination); - - Appender appender = null; - if (destinationOptions.containsKey(FILE)) { - log.debug("found destination entry with type 'file' for: {}", filterDestination); - appender = getFileAppender(filterDestination, destinationOptions.get(FILE)); - } else if (destinationOptions.containsKey("address")) { - log.debug("found destination entry with type 'eventBus' for: {}", filterDestination); - appender = getEventBusAppender(filterDestination, destinationOptions); - } else { - log.warn("Unknown typeLocation for destination: {}", filterDestination); + Appender appender = getAppenderForDestination(filterDestination, destinationOptions); + if (appender != null && !loggers.containsKey(filterDestination)) { + org.apache.logging.log4j.Logger logger = LogManager.getLogger("LOG_FILTER_" + payloadFilter.get(URL)); + ((org.apache.logging.log4j.core.Logger) logger).addAppender(appender); + ((org.apache.logging.log4j.core.Logger) logger).setAdditive(false); + loggers.put(filterDestination, logger); } - - if (appender != null) { - if (!loggers.containsKey(filterDestination)) { - org.apache.logging.log4j.Logger filterLogger = LogManager.getLogger("LOG_FILTER_" + payloadFilter.get(URL)); - ((org.apache.logging.log4j.core.Logger) filterLogger).addAppender(appender); - ((org.apache.logging.log4j.core.Logger) filterLogger).setAdditive(false); - loggers.put(filterDestination, filterLogger); - } - } else { - loggers.put(filterDestination, LogManager.getLogger(DEFAULT_LOGGER)); - } - } - // ... or use the default logger - else { - if (!filterDestination.equals(DEFAULT)) { - log.warn("no destination entry with name '{}' found, using default logger instead", filterDestination); - } - - // use default logger! + } else { loggers.put(filterDestination, LogManager.getLogger(DEFAULT_LOGGER)); } return filterDestination; } - /** - * Returns the eventBus appender matching the given - * filterDestination. If no appender exists for the - * given filterDestination, a new one is created and - * returned. - * - * @param filterDestination - * @param destinationOptions - * @return - */ - private Appender getEventBusAppender(String filterDestination, Map destinationOptions) { - if (!logAppenderRepository.hasAppender(filterDestination)) { - - /* - * - * - * - * - * - * - */ - EventBusAppender.Builder.setEventBus(eventBus); - EventBusAppender appender = EventBusAppender.newBuilder().setName(filterDestination) - .setAddress(destinationOptions.get(ADDRESS)) - .setDeliveryOptionsHeaders(MultiMap.caseInsensitiveMultiMap() - .add(META_DATA, destinationOptions.get(META_DATA))) - .setTransmissionMode(EventBusWriter.TransmissionMode.fromString(destinationOptions.get(TRANSMISSION))) - .setLayout(PatternLayout.createDefaultLayout()).build(); - logAppenderRepository.addAppender(filterDestination, appender); + private Appender getAppenderForDestination(String filterDestination, Map destinationOptions) { + if (logAppenderRepository.hasAppender(filterDestination)) { + return logAppenderRepository.getAppender(filterDestination); } - return logAppenderRepository.getAppender(filterDestination); - } - /** - * Returns the file appender matching the given - * filterDestination. If no appender exists for the - * given filterDestination, a new one is created and - * returned. - * - * @param filterDestination - * @param fileName - * @return - */ - private Appender getFileAppender(String filterDestination, String fileName) { - if (!logAppenderRepository.hasAppender(filterDestination)) { - - /* - * - * - * - * - * - * - * - * - */ - - log.debug("file path: {}", System.getProperty(LOGGING_DIR_PROPERTY) + fileName); - - RollingFileAppender.Builder builder = RollingFileAppender.newBuilder().withPolicy(new TimeBasedTriggeringPolicy.Builder().withInterval(1).build()); - - builder.setName(filterDestination); + if (destinationOptions.containsKey("file")) { + String fileName = destinationOptions.get("file"); + RollingFileAppender.Builder builder = RollingFileAppender.newBuilder(); builder.withFileName(System.getProperty(LOGGING_DIR_PROPERTY) + fileName); builder.withAppend(true); - PatternLayout layout = PatternLayout.createDefaultLayout(); - builder.setLayout(layout); - logAppenderRepository.addAppender(filterDestination, builder.build()); + builder.withLayout(PatternLayout.createDefaultLayout()); + builder.withName(filterDestination); + Appender appender = builder.build(); + logAppenderRepository.addAppender(filterDestination, appender); + return appender; } - - return logAppenderRepository.getAppender(filterDestination); + return null; } public void setResponse(HttpClientResponse response) { diff --git a/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/RequestPropertyFilter.java b/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/RequestPropertyFilter.java index 291762a86..3bc64b798 100644 --- a/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/RequestPropertyFilter.java +++ b/gateleen-logging/src/main/java/org/swisspush/gateleen/logging/RequestPropertyFilter.java @@ -1,6 +1,5 @@ package org.swisspush.gateleen.logging; - import io.vertx.core.MultiMap; import io.vertx.core.http.HttpServerRequest; import org.slf4j.Logger; @@ -12,6 +11,8 @@ /** * Class RequestPropertyFilter provides methods to filterProperty requests. * + * Updated to accept precompiled regex patterns. + * * @author https://github.com/mcweba [Marc-Andre Weber] */ public class RequestPropertyFilter { @@ -20,66 +21,63 @@ public class RequestPropertyFilter { public static final String METHOD = "method"; /** - * Check the provided request against the filterProperty values (key, value) and return a {@link FilterResult} defining + * Check the provided request against the filterProperty values (key, pattern) and return a {@link FilterResult} defining * whether to filterProperty the request or not. * * @param request the request to be checked to filterProperty or not * @param filterPropertyKey the key of the filterProperty e.g. url, method - * @param filterPropertyValue the value of the filterProperty + * @param filterPropertyPattern the precompiled regex pattern of the filterProperty * @param reject boolean value from the filterProperty entry called "reject" * @return the {@link FilterResult} for the provided request */ - public static FilterResult filterProperty(HttpServerRequest request, String filterPropertyKey, String filterPropertyValue, boolean reject) { - + public static FilterResult filterProperty(HttpServerRequest request, String filterPropertyKey, Pattern filterPropertyPattern, boolean reject) { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.setAll(request.headers()); if (URL.equals(filterPropertyKey)) { - boolean matches = filterRequestURL(request, filterPropertyValue); + boolean matches = filterRequestURL(request, filterPropertyPattern); FilterResult result = rejectIfNeeded(reject, matches); - logFilterResult(request, filterPropertyKey, filterPropertyValue, result); + logFilterResult(request, filterPropertyKey, filterPropertyPattern.pattern(), result); return result; } if (METHOD.equals(filterPropertyKey)) { - boolean matches = filterRequestMethod(request, filterPropertyValue); + boolean matches = filterRequestMethod(request, filterPropertyPattern); FilterResult result = rejectIfNeeded(reject, matches); - logFilterResult(request, filterPropertyKey, filterPropertyValue, result); + logFilterResult(request, filterPropertyKey, filterPropertyPattern.pattern(), result); return result; } - if (headers.names().contains(filterPropertyKey) && headers.get(filterPropertyKey).equalsIgnoreCase(filterPropertyValue)) { + if (headers.names().contains(filterPropertyKey) && filterPropertyPattern.matcher(headers.get(filterPropertyKey)).matches()) { FilterResult result = reject ? FilterResult.REJECT : FilterResult.FILTER; - logFilterResult(request, filterPropertyKey, filterPropertyValue, result); + logFilterResult(request, filterPropertyKey, filterPropertyPattern.pattern(), result); return result; } - logFilterResult(request, filterPropertyKey, filterPropertyValue, FilterResult.REJECT, true); + logFilterResult(request, filterPropertyKey, filterPropertyPattern.pattern(), FilterResult.REJECT, true); return FilterResult.REJECT; } private static FilterResult rejectIfNeeded(boolean reject, boolean matches) { - if(!matches){ + if (!matches) { return FilterResult.NO_MATCH; } return reject ? FilterResult.REJECT : FilterResult.FILTER; } - private static boolean filterRequestURL(HttpServerRequest request, String url) { - Pattern urlPattern = Pattern.compile(url); + private static boolean filterRequestURL(HttpServerRequest request, Pattern urlPattern) { Matcher urlMatcher = urlPattern.matcher(request.uri()); return urlMatcher.matches(); } - private static boolean filterRequestMethod(HttpServerRequest request, String method) { - Pattern methodPattern = Pattern.compile(method); + private static boolean filterRequestMethod(HttpServerRequest request, Pattern methodPattern) { Matcher methodMatcher = methodPattern.matcher(request.method().toString()); return methodMatcher.matches(); } - private static void logFilterResult(HttpServerRequest request, String filterPropertyKey, String filterPropertyValue, FilterResult filterResult){ + private static void logFilterResult(HttpServerRequest request, String filterPropertyKey, String filterPropertyValue, FilterResult filterResult) { logFilterResult(request, filterPropertyKey, filterPropertyValue, filterResult, false); } - private static void logFilterResult(HttpServerRequest request, String filterPropertyKey, String filterPropertyValue, FilterResult filterResult, boolean noMatchingProperty){ - if(FilterResult.NO_MATCH != filterResult) { + private static void logFilterResult(HttpServerRequest request, String filterPropertyKey, String filterPropertyValue, FilterResult filterResult, boolean noMatchingProperty) { + if (FilterResult.NO_MATCH != filterResult) { Logger log = RequestLoggerFactory.getLogger(RequestPropertyFilter.class, request); if (!log.isInfoEnabled()) return; StringBuilder sb = new StringBuilder("Request to ").append(request.uri()); diff --git a/gateleen-logging/src/test/java/org/swisspush/gateleen/logging/RequestPropertyFilterTest.java b/gateleen-logging/src/test/java/org/swisspush/gateleen/logging/RequestPropertyFilterTest.java index a5900f486..8f15e73a1 100644 --- a/gateleen-logging/src/test/java/org/swisspush/gateleen/logging/RequestPropertyFilterTest.java +++ b/gateleen-logging/src/test/java/org/swisspush/gateleen/logging/RequestPropertyFilterTest.java @@ -1,7 +1,6 @@ package org.swisspush.gateleen.logging; import io.vertx.core.MultiMap; - import io.vertx.core.http.HttpMethod; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; @@ -9,111 +8,129 @@ import org.junit.runner.RunWith; import org.swisspush.gateleen.core.http.DummyHttpServerRequest; +import java.util.regex.Pattern; + /** * Tests for the {@link RequestPropertyFilter} class * - * @author https://github.com/mcweba [Marc-Andre Weber] + * Updated to use precompiled regex patterns. + * + * @author https://github.com/mcweba */ @RunWith(VertxUnitRunner.class) public class RequestPropertyFilterTest { private final String METHOD_PUT = "PUT"; - private final String METHOD_PUT_POST_REGEX = "PUT|POST"; - private final String METHOD_GET = "GET"; private final String PUT_REQUEST_REGEX = "/playground/server/.*"; - private final String PUT_REQUEST_URI = "/playground/server/some_resource"; - private final String OTHER_PUT_REQUEST_URI = "/playground/server/some_other_resource"; @Test - public void testPropertyUrlFilterRequest(TestContext context){ + public void testPropertyUrlFilterRequest(TestContext context) { context.assertEquals(FilterResult.FILTER, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, PUT_REQUEST_REGEX, false)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, Pattern.compile(PUT_REQUEST_REGEX), false)); } @Test - public void testPropertyUrlRejectRequest(TestContext context){ + public void testPropertyUrlRejectRequest(TestContext context) { context.assertEquals(FilterResult.REJECT, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, PUT_REQUEST_REGEX, true)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, Pattern.compile(PUT_REQUEST_REGEX), true)); } @Test - public void testPropertyUrlNoMatchRequest(TestContext context){ + public void testPropertyUrlNoMatchRequest(TestContext context) { + String OTHER_PUT_REQUEST_URI = "/playground/server/some_other_resource"; context.assertEquals(FilterResult.NO_MATCH, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, OTHER_PUT_REQUEST_URI, true)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.URL, Pattern.compile(OTHER_PUT_REQUEST_URI), true)); } @Test - public void testPropertyMethodFilterRequest(TestContext context){ + public void testPropertyMethodFilterRequest(TestContext context) { context.assertEquals(FilterResult.FILTER, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, METHOD_PUT, false)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, Pattern.compile(METHOD_PUT), false)); + String METHOD_PUT_POST_REGEX = "PUT|POST"; context.assertEquals(FilterResult.FILTER, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, METHOD_PUT_POST_REGEX, false)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, Pattern.compile(METHOD_PUT_POST_REGEX), false)); } @Test - public void testPropertyMethodRejectRequest(TestContext context){ + public void testPropertyMethodRejectRequest(TestContext context) { context.assertEquals(FilterResult.REJECT, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, METHOD_PUT, true)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, Pattern.compile(METHOD_PUT), true)); } @Test - public void testPropertyMethodNoMatchRequest(TestContext context){ + public void testPropertyMethodNoMatchRequest(TestContext context) { + String METHOD_GET = "GET"; context.assertEquals(FilterResult.NO_MATCH, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, METHOD_GET, false)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, Pattern.compile(METHOD_GET), false)); // check again with reject = true context.assertEquals(FilterResult.NO_MATCH, - RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, METHOD_GET, true)); + RequestPropertyFilter.filterProperty(new PUTRequest(), RequestPropertyFilter.METHOD, Pattern.compile(METHOD_GET), true)); } @Test - public void testPropertyHeaderFilterRequest(TestContext context){ + public void testPropertyHeaderFilterRequest(TestContext context) { PUTRequest request = new PUTRequest(); String headerName = "some_fancy_header"; String headerValue = "a_fancy_value"; request.addHeader(headerName, headerValue); - context.assertEquals(FilterResult.FILTER, RequestPropertyFilter.filterProperty(request, headerName, headerValue, false)); + context.assertEquals(FilterResult.FILTER, + RequestPropertyFilter.filterProperty(request, headerName, Pattern.compile(headerValue), false)); } @Test - public void testPropertyHeaderRejectRequest(TestContext context){ + public void testPropertyHeaderRejectRequest(TestContext context) { PUTRequest request = new PUTRequest(); String headerName = "some_fancy_header"; String headerValue = "a_fancy_value"; request.addHeader(headerName, headerValue); - context.assertEquals(FilterResult.REJECT, RequestPropertyFilter.filterProperty(request, headerName, headerValue, true)); + context.assertEquals(FilterResult.REJECT, + RequestPropertyFilter.filterProperty(request, headerName, Pattern.compile(headerValue), true)); } @Test - public void testPropertyHeaderNotMatchingRequest(TestContext context){ + public void testPropertyHeaderNotMatchingRequest(TestContext context) { PUTRequest request = new PUTRequest(); String headerName = "some_fancy_header"; String headerValue = "a_fancy_value"; request.addHeader(headerName, headerValue); // reject = true - context.assertEquals(FilterResult.REJECT, RequestPropertyFilter.filterProperty(request, headerName, "another_fancy_value", true)); - context.assertEquals(FilterResult.REJECT, RequestPropertyFilter.filterProperty(request, "another_fancy_header", headerValue, true)); + context.assertEquals(FilterResult.REJECT, + RequestPropertyFilter.filterProperty(request, headerName, Pattern.compile("another_fancy_value"), true)); + context.assertEquals(FilterResult.REJECT, + RequestPropertyFilter.filterProperty(request, "another_fancy_header", Pattern.compile(headerValue), true)); // reject = false - context.assertEquals(FilterResult.REJECT, RequestPropertyFilter.filterProperty(request, headerName, "another_fancy_value", false)); - context.assertEquals(FilterResult.REJECT, RequestPropertyFilter.filterProperty(request, "another_fancy_header", headerValue, false)); + context.assertEquals(FilterResult.REJECT, + RequestPropertyFilter.filterProperty(request, headerName, Pattern.compile("another_fancy_value"), false)); + context.assertEquals(FilterResult.REJECT, + RequestPropertyFilter.filterProperty(request, "another_fancy_header", Pattern.compile(headerValue), false)); } class PUTRequest extends DummyHttpServerRequest { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - @Override public HttpMethod method() { + @Override + public HttpMethod method() { return HttpMethod.PUT; } - @Override public String uri() { - return PUT_REQUEST_URI; + + @Override + public String uri() { + return "/playground/server/some_resource"; + } + + @Override + public MultiMap headers() { + return headers; } - @Override public MultiMap headers() { return headers; } - public void addHeader(String headerName, String headerValue){ headers.add(headerName, headerValue); } + public void addHeader(String headerName, String headerValue) { + headers.add(headerName, headerValue); + } } }