Skip to content

Commit 47f5985

Browse files
committed
feat: Validate string formats 'uri' and 'uri-reference'
1 parent 2f363d4 commit 47f5985

2 files changed

Lines changed: 53 additions & 5 deletions

File tree

src/main/java/com/retailsvc/http/validate/DefaultValidator.java

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import com.retailsvc.http.spec.schema.StringSchema;
2222
import com.retailsvc.http.spec.schema.TypeName;
2323
import java.math.BigDecimal;
24+
import java.net.URI;
25+
import java.net.URISyntaxException;
2426
import java.time.LocalDate;
2527
import java.time.OffsetDateTime;
2628
import java.time.format.DateTimeParseException;
@@ -46,11 +48,16 @@ private record FormatCheck(Predicate<String> isValid, String message) {}
4648
private static final Pattern EMAIL = Pattern.compile("^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$");
4749

4850
private static final Map<String, FormatCheck> FORMAT_CHECKS =
49-
Map.of(
50-
"uuid", new FormatCheck(DefaultValidator::isUuid, "not a valid uuid"),
51-
"date", new FormatCheck(DefaultValidator::isDate, "not a valid date"),
52-
"date-time", new FormatCheck(DefaultValidator::isDateTime, "not a valid date-time"),
53-
"email", new FormatCheck(s -> EMAIL.matcher(s).matches(), "not a valid email"));
51+
Map.ofEntries(
52+
Map.entry("uuid", new FormatCheck(DefaultValidator::isUuid, "not a valid uuid")),
53+
Map.entry("date", new FormatCheck(DefaultValidator::isDate, "not a valid date")),
54+
Map.entry(
55+
"date-time", new FormatCheck(DefaultValidator::isDateTime, "not a valid date-time")),
56+
Map.entry("email", new FormatCheck(s -> EMAIL.matcher(s).matches(), "not a valid email")),
57+
Map.entry("uri", new FormatCheck(DefaultValidator::isUri, "not a valid uri")),
58+
Map.entry(
59+
"uri-reference",
60+
new FormatCheck(DefaultValidator::isUriReference, "not a valid uri-reference")));
5461

5562
private final Function<String, Schema> refResolver;
5663
private final ConcurrentMap<String, Pattern> compiledPatterns = new ConcurrentHashMap<>();
@@ -158,6 +165,23 @@ private static boolean isDateTime(String s) {
158165
}
159166
}
160167

168+
private static boolean isUri(String s) {
169+
try {
170+
return new URI(s).isAbsolute();
171+
} catch (URISyntaxException _) {
172+
return false;
173+
}
174+
}
175+
176+
private static boolean isUriReference(String s) {
177+
try {
178+
new URI(s);
179+
return true;
180+
} catch (URISyntaxException _) {
181+
return false;
182+
}
183+
}
184+
161185
private void validateInteger(Object value, IntegerSchema s, String pointer) {
162186
long n;
163187
switch (value) {

src/test/java/com/retailsvc/http/validate/StringIntegerNumberTest.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,30 @@ void stringFormatEmail() {
7979
.isEqualTo("format");
8080
}
8181

82+
@Test
83+
void stringFormatUri() {
84+
StringSchema s = new StringSchema(Set.of(TypeName.STRING), null, null, null, "uri", null);
85+
assertThatCode(() -> v.validate("https://example.com/path", s, "/v"))
86+
.doesNotThrowAnyException();
87+
assertThatThrownBy(() -> v.validate("/relative/path", s, "/v"))
88+
.extracting(t -> ((ValidationException) t).error().keyword())
89+
.isEqualTo("format");
90+
assertThatThrownBy(() -> v.validate("not a uri at all", s, "/v"))
91+
.extracting(t -> ((ValidationException) t).error().keyword())
92+
.isEqualTo("format");
93+
}
94+
95+
@Test
96+
void stringFormatUriReference() {
97+
StringSchema s =
98+
new StringSchema(Set.of(TypeName.STRING), null, null, null, "uri-reference", null);
99+
assertThatCode(() -> v.validate("https://example.com", s, "/v")).doesNotThrowAnyException();
100+
assertThatCode(() -> v.validate("/relative/path", s, "/v")).doesNotThrowAnyException();
101+
assertThatThrownBy(() -> v.validate("ht tp://broken", s, "/v"))
102+
.extracting(t -> ((ValidationException) t).error().keyword())
103+
.isEqualTo("format");
104+
}
105+
82106
@Test
83107
void integerWithMinMax() {
84108
IntegerSchema s =

0 commit comments

Comments
 (0)