#1450 - Fix template variable cleanup for variables using regular expressions.

Switched to manual parsing of template variables as regular expressions can contain { and } characters which makes matching variables using these as delimiters impossible.

Related ticket: #1412.
This commit is contained in:
Oliver Drotbohm
2021-02-10 21:09:37 +01:00
parent c561822a45
commit 0f2ac8ecac
2 changed files with 47 additions and 17 deletions

View File

@@ -25,7 +25,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -47,7 +46,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
public class AnnotationMappingDiscoverer implements MappingDiscoverer {
private static final Pattern MULTIPLE_SLASHES = Pattern.compile("/{2,}");
private static final Pattern TEMPLATE_VARIABLE_NAME = Pattern.compile("\\{(.*)\\}");
private final Class<? extends Annotation> annotationType;
private final String mappingAttributeName;
@@ -225,23 +223,44 @@ public class AnnotationMappingDiscoverer implements MappingDiscoverer {
return MULTIPLE_SLASHES.matcher(result.toString()).replaceAll("/");
}
private static String cleanupPart(String variable) {
private static String cleanupPart(String part) {
if (!variable.contains("{")) {
return variable;
StringBuilder builder = new StringBuilder();
int level = 0;
boolean inRegex = false;
for (int i = 0; i < part.length(); i++) {
char character = part.charAt(i);
if (character == '{') {
level++;
if (level == 1) {
builder.append(character);
continue;
}
}
if (level == 1 && character == ':') {
inRegex = true;
}
if (character == '}') {
level--;
if (level == 0) {
inRegex = false;
}
}
if (!inRegex) {
builder.append(character);
}
}
Matcher matcher = TEMPLATE_VARIABLE_NAME.matcher(variable);
if (!matcher.find()) {
return variable;
}
String rawName = matcher.group(1);
int colonIndex = rawName.indexOf(':');
return colonIndex < 0
? variable
: variable.replace(matcher.group(0), "{" + rawName.substring(0, colonIndex) + "}");
return builder.toString();
}
}

View File

@@ -171,6 +171,14 @@ class AnnotationMappingDiscovererUnitTest {
assertThat(discoverer.getConsumes(method)).isEmpty();
}
@Test // #1450
void extractsMultipleRegularExpressionVariablesCorrectly() throws Exception {
Method method = MyController.class.getMethod("multipleRegularExpressions");
assertThat(discoverer.getMapping(method)).isEqualTo("/type/spring-web/{symbolicName}-{version}{extension}");
}
@RequestMapping("/type")
interface MyController {
@@ -188,6 +196,9 @@ class AnnotationMappingDiscovererUnitTest {
@RequestMapping(path = "/path", consumes = "application/json")
void mappingWithConsumesClause();
@GetMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
void multipleRegularExpressions();
}
interface ControllerWithoutTypeLevelMapping {