-
Notifications
You must be signed in to change notification settings - Fork 0
/
loader.go
84 lines (67 loc) · 1.72 KB
/
loader.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
package loader
import (
"context"
"errors"
"fmt"
"io/fs"
"net/url"
"os"
"strings"
"syscall"
)
type Loader interface {
Load(ctx context.Context) ([]byte, error)
}
type GeneralLoader struct {
loader Loader
}
var _ Loader = (*GeneralLoader)(nil)
var (
ErrInvalidPath = errors.New("invalid local or remote path")
ErrInvalidLocalPath = errors.New("failed to load the local file")
ErrInvalidRemotePath = errors.New("failed to load the remote file")
ErrNoFileToLoad = errors.New("specific loader is not properly configured")
)
func NewGeneralLoader(filePath string) (*GeneralLoader, error) {
var generic GeneralLoader
if isRemotePath(filePath) {
generic.loader = NewRemoteLoader(filePath)
} else if isLocalPath(filePath) {
generic.loader = NewLocalLoader(filePath)
}
if generic.loader == nil {
return nil, fmt.Errorf("%w: %s", ErrInvalidPath, filePath)
}
return &generic, nil
}
func (l *GeneralLoader) Load(ctx context.Context) ([]byte, error) {
if l.loader == nil {
return nil, ErrNoFileToLoad
}
return l.loader.Load(ctx)
}
func isLocalPath(path string) bool {
// We make sure it isn't a directory.
if strings.HasSuffix(path, string(os.PathSeparator)) {
return false
}
if _, err := os.Stat(path); err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
if errors.Is(pathErr.Err, syscall.EINVAL) {
// It's definitely an invalid character in the filepath.
return false
}
}
}
// It could be a permission error, a does-not-exist error, etc.
// Out-of-scope for this validation, though.
return true
}
func isRemotePath(path string) bool {
parsed, err := url.Parse(path)
if err != nil {
return false
}
return parsed.Scheme == "http" || parsed.Scheme == "https"
}