#1455 - 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: #1414.
This commit is contained in:
Oliver Drotbohm
2021-02-10 21:09:37 +01:00
parent 93cdc2d887
commit 1192eba607
2 changed files with 47 additions and 17 deletions

View File

@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.http.HttpMethod;
@@ -42,7 +41,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;
@@ -205,23 +203,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

@@ -160,6 +160,14 @@ class AnnotationMappingDiscovererUnitTest {
assertThat(discoverer.getMapping(method)).isEqualTo("/type/foo/{bar}");
}
@Test // #1455
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 {
@@ -174,6 +182,9 @@ class AnnotationMappingDiscovererUnitTest {
@RequestMapping("/foo/{bar:[ABC]{1}}")
void mappingWithMatchingExpression();
@GetMapping("/spring-web/{symbolicName:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{extension:\\.[a-z]+}")
void multipleRegularExpressions();
}
interface ControllerWithoutTypeLevelMapping {