diff --git a/Sources/JSONSchema.swift b/Sources/JSONSchema.swift index c4d5c81..b00bdad 100644 --- a/Sources/JSONSchema.swift +++ b/Sources/JSONSchema.swift @@ -61,6 +61,7 @@ public struct Schema { formats = [ "ipv4": validateIPv4, "ipv6": validateIPv6, + "uri": validateURI, ] } diff --git a/Sources/Validators.swift b/Sources/Validators.swift index 6b7d55f..6ae6dc7 100644 --- a/Sources/Validators.swift +++ b/Sources/Validators.swift @@ -423,3 +423,23 @@ func validateIPv6(_ value:Any) -> ValidationResult { return .Valid } + +func validateURI(_ value:Any) -> ValidationResult { + if let uri = value as? String { + // Using the regex from http://blog.dieweltistgarnichtso.net/constructing-a-regular-expression-that-matches-uris + + if let expression = try? NSRegularExpression(pattern: "((?<=\\()[A-Za-z][A-Za-z0-9\\+\\.\\-]*:([A-Za-z0-9\\.\\-_~:/\\?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=]|%[A-Fa-f0-9]{2})+(?=\\)))|([A-Za-z][A-Za-z0-9\\+\\.\\-]*:([A-Za-z0-9\\.\\-_~:/\\?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=]|%[A-Fa-f0-9]{2})+)", options: NSRegularExpression.Options(rawValue: 0)) { + let result = expression.matches(in: uri, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, uri.characters.count)) + if result.count == 1 { + let foundRange = result[0].range + if foundRange.location == 0 && foundRange.length == uri.characters.count { + return .Valid + } + } + } + + return .invalid(["'\(uri)' is not a valid URI."]) + } + + return .Valid +}