-
Notifications
You must be signed in to change notification settings - Fork 0
/
scheme.go
99 lines (83 loc) · 2.73 KB
/
scheme.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package resource
import (
"fmt"
"strings"
)
const (
SchemeSeparator = "://"
StringScheme = "string"
BytesScheme = "bytes"
FileScheme = "file"
HTTPScheme = "http"
HTTPSScheme = "https"
)
// Split parses a resource value into its scheme and value.
// This is much more relaxed than url.Parse, as it permits characters
// that are not allowed in URIs. This fact is importent when allowing
// arbitrary strings or bytes as in-memory resources.
func Split(v string) (scheme, value string) {
if i := strings.Index(v, SchemeSeparator); i >= 0 {
return v[0:i], v[i+len(SchemeSeparator):]
}
return "", v
}
// NewDefaultSchemeResolvers produces a Resolvers with the default scheme mappings.
// These mappings are:
//
// StringScheme is mapped to a StringResolver
// BytesScheme is mapped to a BytesResolver with standard base64 encoding
// FileScheme is mapped to a FileResolver with no relative path
// HTTPScheme and HTTPSScheme are mapped to an HTTPResolver using the default HTTP Client
//
// When constructing custom SchemeResolver instances, this function is useful as a starting point.
func NewDefaultSchemeResolvers() Resolvers {
var (
fr = FileResolver{}
hr = HTTPResolver{}
)
return Resolvers{
StringScheme: StringResolver{},
BytesScheme: BytesResolver{},
FileScheme: fr,
HTTPScheme: hr,
HTTPSScheme: hr,
}
}
// SchemeError is returned when a scheme had no associated resolver.
type SchemeError struct {
Value string
Scheme string
}
func (e SchemeError) Error() string {
return fmt.Sprintf("Cannot resolve %s: no resolver registered for scheme %s", e.Value, e.Scheme)
}
// NoSchemeError is returned when no scheme was supplied on a resource and the SchemeResolver
// had no NoScheme resolver configured.
type NoSchemeError struct {
Value string
}
func (e NoSchemeError) Error() string {
return fmt.Sprintf("Cannot resolve %s: no scheme supplied", e.Value)
}
// SchemeResolver is a resource resolver that uses URI-style schemes to determine how to
// resolve resources. For example, "http://localhost/foo" is a resource value with the scheme "http".
// Resource values resolved by this type of resolver do not have to be well-formed URIs unless the
// component resolver expects that. For example, "string://hello world" would resolve to a string
// resource when using the default scheme resolver.
type SchemeResolver struct {
Resolvers Resolvers
NoScheme Resolver
}
func (sr SchemeResolver) Resolve(v string) (Interface, error) {
if scheme, _ := Split(v); len(scheme) > 0 {
resolver, ok := sr.Resolvers.Get(scheme)
if !ok {
return nil, SchemeError{Value: v, Scheme: scheme}
}
return resolver.Resolve(v)
}
if sr.NoScheme == nil {
return nil, NoSchemeError{Value: v}
}
return sr.NoScheme.Resolve(v)
}