/** * Shortcut method for setting the same property on the underlying pattern * parser in use. For more details see: * <ul> * <li>{@link #getPathPatternParser()} -- the underlying pattern parser * <li>{@link PathPatternParser#setMatchOptionalTrailingSeparator(boolean)} -- * the trailing slash option, including its default value. * </ul> */ public void setUseTrailingSlashMatch(boolean trailingSlashMatch) { this.patternParser.setMatchOptionalTrailingSeparator(trailingSlashMatch); }
private PathPattern parse(String path) { PathPatternParser pp = new PathPatternParser(); pp.setMatchOptionalTrailingSeparator(true); return pp.parse(path); }
@Override public Predicate<ServerWebExchange> apply(Config config) { final ArrayList<PathPattern> pathPatterns = new ArrayList<>(); synchronized (this.pathPatternParser) { pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchOptionalTrailingSeparator()); config.getPatterns().forEach(pattern -> { PathPattern pathPattern = this.pathPatternParser.parse(pattern); pathPatterns.add(pathPattern); }); } return exchange -> { PathContainer path = parsePath(exchange.getRequest().getURI().getPath()); Optional<PathPattern> optionalPathPattern = pathPatterns.stream() .filter(pattern -> pattern.matches(path)) .findFirst(); if (optionalPathPattern.isPresent()) { PathPattern pathPattern = optionalPathPattern.get(); traceMatch("Pattern", pathPattern.getPatternString(), path, true); PathMatchInfo pathMatchInfo = pathPattern.matchAndExtract(path); putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables()); return true; } else { traceMatch("Pattern", config.getPatterns(), path, false); return false; } }; }
private void checkMatches(String uriTemplate, String path) { PathPatternParser parser = new PathPatternParser(); parser.setMatchOptionalTrailingSeparator(true); PathPattern p = parser.parse(uriTemplate); PathContainer pc = toPathContainer(path); assertTrue(p.matches(pc)); }
@Test public void matchTrailingSlash() throws Exception { MockServerWebExchange exchange = MockServerWebExchange.from(get("/foo/")); PatternsRequestCondition condition = createPatternsCondition("/foo"); PatternsRequestCondition match = condition.getMatchingCondition(exchange); assertNotNull(match); assertEquals("Should match by default", "/foo", match.getPatterns().iterator().next().getPatternString()); condition = createPatternsCondition("/foo"); match = condition.getMatchingCondition(exchange); assertNotNull(match); assertEquals("Trailing slash should be insensitive to useSuffixPatternMatch settings (SPR-6164, SPR-5636)", "/foo", match.getPatterns().iterator().next().getPatternString()); PathPatternParser parser = new PathPatternParser(); parser.setMatchOptionalTrailingSeparator(false); condition = new PatternsRequestCondition(parser.parse("/foo")); match = condition.getMatchingCondition(MockServerWebExchange.from(get("/foo/"))); assertNull(match); }
@Test public void wildcards() { checkMatches("/*/bar", "/foo/bar"); checkNoMatch("/*/bar", "/foo/baz"); checkNoMatch("/*/bar", "//bar"); checkMatches("/f*/bar", "/foo/bar"); checkMatches("/*/bar", "/foo/bar"); checkMatches("a/*","a/"); checkMatches("/*","/"); checkMatches("/*/bar", "/foo/bar"); checkNoMatch("/*/bar", "/foo/baz"); checkMatches("/f*/bar", "/foo/bar"); checkMatches("/*/bar", "/foo/bar"); checkMatches("/a*b*c*d/bar", "/abcd/bar"); checkMatches("*a*", "testa"); checkMatches("a/*", "a/"); checkNoMatch("a/*", "a//"); // no data for * checkMatches("a/*", "a/a/"); // trailing slash, so is allowed PathPatternParser ppp = new PathPatternParser(); ppp.setMatchOptionalTrailingSeparator(false); assertFalse(ppp.parse("a/*").matches(toPathContainer("a//"))); checkMatches("a/*", "a/a"); checkMatches("a/*", "a/a/"); // trailing slash is optional checkMatches("/resource/**", "/resource"); checkNoMatch("/resource/**", "/resourceX"); checkNoMatch("/resource/**", "/resourceX/foobar"); checkMatches("/resource/**", "/resource/foobar"); }
ppp.setMatchOptionalTrailingSeparator(true); pp = ppp.parse("/****"); assertMatches(pp,"/abcdef");