HttpPathValidator { public static void validate(HttpPath httpPath) { Path path = Paths.get(httpPath.get()); Preconditions.checkArgument( path.isAbsolute(), "Conjure paths must be absolute, i.e., start with '/': %s", path); Preconditions.checkArgument( path.getSegments().isEmpty() || !path.isFolder(), "Conjure paths must not end with a '/': %s", path); for (String segment : path.getSegments()) { Preconditions.checkArgument( SEGMENT_PATTERN.matcher(segment).matches() || PARAM_SEGMENT_PATTERN.matcher(segment).matches() || PARAM_REGEX_SEGMENT_PATTERN.matcher(segment).matches(), "Segment %s of path %s did not match required segment patterns %s or parameter name " + "patterns %s or %s", segment, path, SEGMENT_PATTERN, PARAM_SEGMENT_PATTERN, PARAM_REGEX_SEGMENT_PATTERN); } Set<String> templateVars = new HashSet<>(); new UriTemplate(path.toString()).getTemplateVariables().forEach(var -> { Preconditions.checkState( !templateVars.contains(var), "Path parameter %s appears more than once in path %s", var, path); templateVars.add(var); }); UriTemplateParser uriTemplateParser = new UriTemplateParser(path.toString()); Map<String, Pattern> nameToPattern = uriTemplateParser.getNameToPattern(); List<String> segments = Splitter.on('/').splitToList(uriTemplateParser.getNormalizedTemplate()); for (int i = 0; i < segments.size(); i++) { String segment = segments.get(i); if (!(segment.startsWith("{") && segment.endsWith("}"))) { continue; } Pattern varPattern = nameToPattern.get(segment.substring(1, segment.length() - 1)); if (varPattern.equals(UriTemplateParser.TEMPLATE_VALUE_PATTERN)) { continue; } Preconditions.checkState( i == segments.size() - 1 || !varPattern.pattern().equals(".*"), "Path parameter %s in path %s specifies regular expression %s, but this regular " + "expression is only permitted if the path parameter is the last segment", segment, path, varPattern); } } private  HttpPathValidator(); static Set<ArgumentName> pathArgs(String httpPath); static void validate(HttpPath httpPath); static String withoutLeadingSlash(String httpPath); static final String PATTERN; }
@Test public void testPathsMustBeAbsolute() { assertThatThrownBy(() -> validate("abc")) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Conjure paths must be absolute, i.e., start with '/': abc"); }
@Test public void testPathSegmentsMustObeySyntax() { for (PathSegmentTestCase currCase : new PathSegmentTestCase[] { new PathSegmentTestCase("/123", "123"), new PathSegmentTestCase("/abc/$%^", "$%^"), new PathSegmentTestCase("/abc/{123}", "{123}"), }) { assertThatThrownBy(() -> validate(currCase.path)) .isInstanceOf(IllegalArgumentException.class) .hasMessage(String.format( "Segment %s of path %s did not match required segment patterns " + "^[a-zA-Z][a-zA-Z0-9._-]*$ or parameter name patterns " + "^\\{[a-z][a-z0-9]*([A-Z0-9][a-z0-9]+)*}$ or " + "^\\{[a-z][a-z0-9]*([A-Z0-9][a-z0-9]+)*" + "(" + Pattern.quote(":.+") + "|" + Pattern.quote(":.*") + ")" + "}$", currCase.invalidSegment, currCase.path)); } }
@Test public void testNonEmptyPathsMustNotEndWithSlash() { assertThatThrownBy(() -> validate("/abc/")) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Conjure paths must not end with a '/': /abc/"); }
@Test public void testValidPaths() { validate("/"); validate("/a/b/c"); validate("/abc"); validate("/{foo}"); validate("/abc/{foo}/bar"); validate("/abc/{foo:.+}"); validate("/abc/v1.2/{foo}"); }