Passed
Pull Request — main (#38)
by Igor
02:08
created

validate.validateProtocol   A

Complexity

Conditions 5

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 7
nop 3
dl 0
loc 12
rs 9.3333
c 0
b 0
f 0
1
package validate
2
3
import (
4
	"errors"
5
	"net/url"
6
)
7
8
var (
9
	ErrUnexpectedProtocol = errors.New("unexpected protocol")
10
)
11
12
// URL is used to validate that value is a valid absolute URL string, which means that a protocol (or scheme)
13
// is required. By default (if no protocols are passed), the function checks only for
14
// the http:// and https:// protocols. Use the protocols argument to configure the list of expected protocols.
15
//
16
// If value is not a valid URL the function will return one of the errors:
17
//	• parsing error from url.Parse method if value cannot be parsed as an URL;
18
//	• ErrUnexpectedProtocol if protocol is not matching one of the listed protocols;
19
//	• ErrInvalid if value is not matching the regular expression.
20
func URL(value string, protocols ...string) error {
21
	return validateURL(value, false, protocols...)
22
}
23
24
// RelativeURL is used to validate that value is a valid absolute or relative URL string. The protocol is considered
25
// optional when validating the syntax of the given URL. This means that both http:// and https:// are valid
26
// but also relative URLs that contain no protocol (e.g. //example.com). By default, the function checks
27
// only for the http:// and https:// protocols. Use the protocols argument to configure
28
// the list of expected protocols.
29
//
30
// If value is not a valid URL the function will return one of the errors:
31
//	• parsing error from url.Parse method if value cannot be parsed as an URL;
32
//	• ErrUnexpectedProtocol if protocol is not matching one of the listed protocols or it is not a relative URL;
33
//	• ErrInvalid if value is not matching the regular expression.
34
func RelativeURL(value string, protocols ...string) error {
35
	return validateURL(value, true, protocols...)
36
}
37
38
func validateURL(value string, isRelative bool, protocols ...string) error {
39
	if len(protocols) == 0 {
40
		protocols = []string{"http", "https"}
41
	}
42
	u, err := url.Parse(value)
43
	if err != nil {
44
		return err
45
	}
46
47
	err = validateProtocol(u, isRelative, protocols)
48
	if err != nil {
49
		return err
50
	}
51
52
	if !urlRegex.MatchString(value) {
53
		return ErrInvalid
54
	}
55
56
	return nil
57
}
58
59
func validateProtocol(u *url.URL, isRelative bool, protocols []string) error {
60
	if isRelative && u.Scheme == "" {
61
		return nil
62
	}
63
64
	for _, protocol := range protocols {
65
		if protocol == u.Scheme {
66
			return nil
67
		}
68
	}
69
70
	return ErrUnexpectedProtocol
71
}
72