Configurable limit on HandlerMappingIntrospector
Closes gh-34918
This commit is contained in:
parent
67ed64a41d
commit
983af78352
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -99,6 +99,8 @@ public class HandlerMappingIntrospector
|
|||
private static final String CACHED_RESULT_ATTRIBUTE =
|
||||
HandlerMappingIntrospector.class.getName() + ".CachedResult";
|
||||
|
||||
private static final int DEFAULT_CACHE_LIMIT = 2048;
|
||||
|
||||
|
||||
@Nullable
|
||||
private ApplicationContext applicationContext;
|
||||
|
@ -108,9 +110,30 @@ public class HandlerMappingIntrospector
|
|||
|
||||
private Map<HandlerMapping, PathPatternMatchableHandlerMapping> pathPatternMappings = Collections.emptyMap();
|
||||
|
||||
private int patternCacheLimit = DEFAULT_CACHE_LIMIT;
|
||||
|
||||
private final CacheResultLogHelper cacheLogHelper = new CacheResultLogHelper();
|
||||
|
||||
|
||||
/**
|
||||
* Set a limit on the maximum number of security patterns passed into
|
||||
* {@link MatchableHandlerMapping#match} at runtime to cache.
|
||||
* <p>By default, this is set to 2048.
|
||||
* @param patternCacheLimit the limit to use
|
||||
* @since 6.2.8
|
||||
*/
|
||||
public void setPatternCacheLimit(int patternCacheLimit) {
|
||||
this.patternCacheLimit = patternCacheLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured limit on security patterns to cache.
|
||||
* @since 6.2.8
|
||||
*/
|
||||
public int getPatternCacheLimit() {
|
||||
return this.patternCacheLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
|
@ -124,8 +147,9 @@ public class HandlerMappingIntrospector
|
|||
|
||||
this.pathPatternMappings = this.handlerMappings.stream()
|
||||
.filter(m -> m instanceof MatchableHandlerMapping hm && hm.getPatternParser() != null)
|
||||
.map(mapping -> (MatchableHandlerMapping) mapping)
|
||||
.collect(Collectors.toMap(mapping -> mapping, PathPatternMatchableHandlerMapping::new));
|
||||
.map(hm -> (MatchableHandlerMapping) hm)
|
||||
.collect(Collectors.toMap(hm -> hm, (MatchableHandlerMapping delegate) ->
|
||||
new PathPatternMatchableHandlerMapping(delegate, getPatternCacheLimit())));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -39,28 +39,29 @@ import org.springframework.web.util.pattern.PathPatternParser;
|
|||
*/
|
||||
class PathPatternMatchableHandlerMapping implements MatchableHandlerMapping {
|
||||
|
||||
private static final int MAX_PATTERNS = 1024;
|
||||
|
||||
|
||||
private final MatchableHandlerMapping delegate;
|
||||
|
||||
private final PathPatternParser parser;
|
||||
|
||||
private final Map<String, PathPattern> pathPatternCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final int cacheLimit;
|
||||
|
||||
public PathPatternMatchableHandlerMapping(MatchableHandlerMapping delegate) {
|
||||
|
||||
public PathPatternMatchableHandlerMapping(MatchableHandlerMapping delegate, int cacheLimit) {
|
||||
Assert.notNull(delegate, "HandlerMapping to delegate to is required.");
|
||||
Assert.notNull(delegate.getPatternParser(), "Expected HandlerMapping configured to use PatternParser.");
|
||||
this.delegate = delegate;
|
||||
this.parser = delegate.getPatternParser();
|
||||
this.cacheLimit = cacheLimit;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RequestMatchResult match(HttpServletRequest request, String pattern) {
|
||||
PathPattern pathPattern = this.pathPatternCache.computeIfAbsent(pattern, value -> {
|
||||
Assert.state(this.pathPatternCache.size() < MAX_PATTERNS, "Max size for pattern cache exceeded.");
|
||||
Assert.state(this.pathPatternCache.size() < this.cacheLimit, "Max size for pattern cache exceeded.");
|
||||
return this.parser.parse(pattern);
|
||||
});
|
||||
PathContainer path = ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication();
|
||||
|
|
Loading…
Reference in New Issue