-
Notifications
You must be signed in to change notification settings - Fork 4
/
url.go
82 lines (72 loc) · 2.22 KB
/
url.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package config
import (
"encoding/json"
"net/url"
"strings"
"gopkg.in/yaml.v3"
)
// URL Custom net.URL compatible with YAML and JSON (un)marshalling and kubebuilder.
// In addition, it also removes trailing slash if present, so we can easily
// append a longer path without having to worry about double slashes.
//
// Allow only http/https URLs or environment variables like ${FOOBAR}
// +kubebuilder:validation:Pattern=`^(https?://.+)|(\$\{.+\}.*)`
// +kubebuilder:validation:Type=string
type URL struct {
// This is a pointer so the wrapper can directly be used in templates, e.g.: {{ .Config.BaseURL }}
// Otherwise you would need .String() or template.URL(). (Might be a bug.)
*url.URL
}
// UnmarshalYAML parses a string to URL and also removes trailing slash if present,
// so we can easily append a longer path without having to worry about double slashes.
func (u *URL) UnmarshalYAML(unmarshal func(any) error) error {
var s string
if err := unmarshal(&s); err != nil {
return err
}
if parsedURL, err := parseURL(s); err != nil {
return err
} else if parsedURL != nil {
u.URL = parsedURL
}
return nil
}
// MarshalJSON turns URL into JSON.
// Value instead of pointer receiver because only that way it can be used for both.
func (u URL) MarshalJSON() ([]byte, error) {
if u.URL == nil {
return json.Marshal("")
}
return json.Marshal(u.URL.String())
}
// UnmarshalJSON parses a string to URL and also removes trailing slash if present,
// so we can easily append a longer path without having to worry about double slashes.
func (u *URL) UnmarshalJSON(b []byte) error {
return yaml.Unmarshal(b, u)
}
// MarshalYAML turns URL into YAML.
// Value instead of pointer receiver because only that way it can be used for both.
func (u URL) MarshalYAML() (interface{}, error) {
if u.URL == nil {
return "", nil
}
return u.URL.String(), nil
}
// DeepCopyInto copies the receiver, writes into out.
func (u *URL) DeepCopyInto(out *URL) {
if out != nil {
*out = *u
}
}
// DeepCopy copies the receiver, creates a new URL.
func (u *URL) DeepCopy() *URL {
if u == nil {
return nil
}
out := &URL{}
u.DeepCopyInto(out)
return out
}
func parseURL(s string) (*url.URL, error) {
return url.ParseRequestURI(strings.TrimSuffix(s, "/"))
}