diff --git a/baked_in.go b/baked_in.go index cc92b7840..986ea2525 100644 --- a/baked_in.go +++ b/baked_in.go @@ -1413,6 +1413,15 @@ func isURI(fl FieldLevel) bool { panic(fmt.Sprintf("Bad field type %T", field.Interface())) } +// isFileURL is the helper function for validating if the `path` valid file URL as per RFC8089 +func isFileURL(path string) bool { + if !strings.HasPrefix(path, "file:/") { + return false + } + _, err := url.ParseRequestURI(path) + return err == nil +} + // isURL is the validation function for validating if the current field's value is a valid URL. func isURL(fl FieldLevel) bool { field := fl.Field() @@ -1420,12 +1429,16 @@ func isURL(fl FieldLevel) bool { switch field.Kind() { case reflect.String: - s := field.String() + s := strings.ToLower(field.String()) if len(s) == 0 { return false } + if isFileURL(s) { + return true + } + url, err := url.Parse(s) if err != nil || url.Scheme == "" { return false diff --git a/validator_test.go b/validator_test.go index 09ff1dfe2..c1bc430e9 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8090,6 +8090,12 @@ func TestUrl(t *testing.T) { {"./rel/test/dir", false}, {"irc:", false}, {"http://", false}, + {"file://path/to/file.txt", true}, + {"file:///c:/Windows/file.txt", true}, + {"file://localhost/path/to/file.txt", true}, + {"file://localhost/c:/WINDOWS/file.txt", true}, + {"file://", true}, + {"file:////remotehost/path/file.txt", true}, } validate := New()