Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Sep 27, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions src/main/java/com/google/api/pathtemplate/PathTemplate.java
Original file line number Diff line number Diff line change
Expand Up @@ -887,9 +887,7 @@ private static ImmutableList<Segment> parseTemplate(String template) {

boolean isLastSegment = (template.indexOf(seg) + seg.length()) == template.length();
boolean isCollectionWildcard = !isLastSegment && (seg.equals("-") || seg.equals("-}"));
if (!isCollectionWildcard
&& (COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(0, 1)).find()
|| COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(seg.length() - 1)).find())) {
if (!isCollectionWildcard && isSegmentBeginOrEndInvalid(seg)) {
throw new ValidationException("parse error: invalid begin or end character in '%s'", seg);
}
// Disallow zero or multiple delimiters between variable names.
Expand Down Expand Up @@ -1015,6 +1013,20 @@ private static ImmutableList<Segment> parseTemplate(String template) {
return builder.build();
}

private static boolean isSegmentBeginOrEndInvalid(String seg) {
// A segment is invalid if it contains only one character and the character is a delimiter
if (seg.length() == 1 && COMPLEX_DELIMITER_PATTERN.matcher(seg).find()) {
return true;
}
// A segment can start with a delimiter, as long as there is no { right after it.
// A segment can end with a delimiter, as long as there is no } right before it.
// e.g. Invalid: .{well}-{known}, {well}-{known}-
// Valid: .well-known, .well-{known}, .-~{well-known}, these segments are all considered as literals for matching
return (COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(0, 1)).find() && seg.charAt(1) == '{')
|| (COMPLEX_DELIMITER_PATTERN.matcher(seg.substring(seg.length() - 1)).find()
&& seg.charAt(seg.length() - 2) == '}');
}

private static List<Segment> parseComplexResourceId(String seg) {
List<Segment> segments = new ArrayList<>();
List<String> separatorIndices = new ArrayList<>();
Expand Down
77 changes: 74 additions & 3 deletions src/test/java/com/google/api/pathtemplate/PathTemplateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -487,9 +487,6 @@ public void complexResourceBasicInvalidIds() {
@Test
public void complexResourceMultipleDelimiters() {
thrown.expect(ValidationException.class);
PathTemplate.create("projects/*/zones/.-~{zone_a}");
thrown.expectMessage(
String.format("parse error: invalid begin or end character in '%s'", ".-~{zone_a}"));

PathTemplate.create("projects/*/zones/{zone_a}~.{zone_b}");
thrown.expectMessage(
Expand Down Expand Up @@ -717,6 +714,80 @@ public void instantiateWithCustomVerbs() {
Truth.assertThat(template.matches(templateInstance)).isTrue();
}

@Test
public void instantiateWithASegmentStartsWithADelimiter() {
PathTemplate pathTemplate =
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/.well-known/openid-configuration");
String pattern =
"v1beta1/projects/abc/locations/def/clusters/yte/.well-known/openid-configuration";
Truth.assertThat(pathTemplate.matches(pattern)).isTrue();
}

@Test
public void instantiateWithASegmentContainingComplexResourceNamesAndStartsWithADelimiter() {
thrown.expect(ValidationException.class);
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/.{well}-{known}/openid-configuration");
thrown.expectMessage(
String.format("parse error: invalid begin or end character in '%s'", ".{well}-{known}"));
}

@Test
public void
instantiateWithASegmentContainingNoComplexResourceNamesAndStartsWithMultipleDelimiters() {
PathTemplate pathTemplate =
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/.-~well-known/openid-configuration");
String pattern =
"v1beta1/projects/abc/locations/def/clusters/yte/.-~well-known/openid-configuration";
Truth.assertThat(pathTemplate.matches(pattern)).isTrue();
}

@Test
public void instantiateWithASegmentOnlyContainingOneDelimiter() {
thrown.expect(ValidationException.class);
PathTemplate.create("v1/publishers/{publisher}/books/.");
thrown.expectMessage(String.format("parse error: invalid begin or end character in '%s'", "."));
}

@Test
public void instantiateWithASegmentOnlyContainingOneCharacter() {
PathTemplate pathTemplate = PathTemplate.create("v1/publishers/{publisher}/books/a");
String pattern = "v1/publishers/o'reilly/books/a";
Truth.assertThat(pathTemplate.matches(pattern)).isTrue();
}

@Test
public void instantiateWithASegmentEndsWithADelimiter() {
PathTemplate pathTemplate =
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/well-known./openid-configuration");
String pattern =
"v1beta1/projects/abc/locations/def/clusters/yte/well-known./openid-configuration";
Truth.assertThat(pathTemplate.matches(pattern)).isTrue();
}

@Test
public void instantiateWithASegmentContainingComplexResourceNamesAndEndsWithADelimiter() {
thrown.expect(ValidationException.class);
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/{well}-{known}./openid-configuration");
thrown.expectMessage(
String.format("parse error: invalid begin or end character in '%s'", "{well}-{known}."));
}

@Test
public void
instantiateWithASegmentContainingNoComplexResourceNamesAndEndsWithMultipleDelimiters() {
PathTemplate pathTemplate =
PathTemplate.create(
"v1beta1/{parent=projects/*/locations/*/clusters/*}/well-known.-~/openid-configuration");
String pattern =
"v1beta1/projects/abc/locations/def/clusters/yte/well-known.-~/openid-configuration";
Truth.assertThat(pathTemplate.matches(pattern)).isTrue();
}

// Other
// =====

Expand Down