-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmatcher.go
97 lines (85 loc) · 2.89 KB
/
matcher.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
package goacors
import (
"context"
"net/url"
"strings"
"github.com/goadesign/goa"
)
// OriginMatcher define behavior domain and origin matcher
type OriginMatcher interface {
FindMatchedOrigin(allowedOrigins []string, origin string) (foundOne string, found bool)
}
// StrictOriginMatcher marker for doing strict check
type StrictOriginMatcher struct {
config *GoaCORSConfig
}
// newStrictOriginMatcher create new OriginMatcher implement
func newStrictOriginMatcher(config *GoaCORSConfig) OriginMatcher {
return &StrictOriginMatcher{config}
}
// FindMatchedOrigin check if allowedOrigins contain * or completely same origin
func (s *StrictOriginMatcher) FindMatchedOrigin(allowedOrigins []string, origin string) (foundOne string, found bool) {
for _, o := range allowedOrigins {
if foundOne, found = innerMatcher(o, origin, s.config.AllowCredentials); found {
return
}
}
return
}
type baseMatcher func(allowedOrigin string, origin string, allowCredentials bool) (filteredOrigin string, ok bool)
var innerMatcher = func(allowedOrigin string, origin string, allowCredentials bool) (filteredOrigin string, ok bool) {
if allowedOrigin == "*" && allowCredentials && origin != "" {
return origin, true
}
if allowedOrigin == "*" || allowedOrigin == origin {
return allowedOrigin, true
}
return
}
// InterMediateMatcher allows subdomain wildcard
type InterMediateMatcher struct {
baseMatcher
config *GoaCORSConfig
}
// newInterMediateMatcher create new OriginMatcher implement
func newInterMediateMatcher(config *GoaCORSConfig) OriginMatcher {
// notify this matcher has weakness for security
goa.LogInfo(context.Background(), "!!!warning!!! you'll use intermediate match mode! note that using this mode is not recommended for production!")
return &InterMediateMatcher{
baseMatcher: innerMatcher,
config: config,
}
}
// Filter returns ok and found one if wildcard matched with subdomain or completely same origin or entirely wildcard
// ** Note **
// first of all, this method will be panic when couldn't parse pre-set allowed origin url.
// second, wild card is enabled only in their host name
func (i *InterMediateMatcher) FindMatchedOrigin(allowedOrigins []string, origin string) (foundOne string, found bool) {
originUrl, err := url.Parse(origin)
if err != nil {
return "", false
}
for _, o := range allowedOrigins {
if foundOne, found = i.baseMatcher(o, origin, i.config.AllowCredentials); found {
return
}
allowedURL, err := url.Parse(o)
if err != nil {
panic(err)
}
if !strings.Contains(allowedURL.Host, "*") {
continue
}
parts := strings.SplitN(allowedURL.Host, "*", 2)
if !strings.HasPrefix(originUrl.Host, parts[0]) ||
!strings.HasSuffix(origin, parts[1]) ||
originUrl.Scheme != allowedURL.Scheme ||
originUrl.Path != allowedURL.Path ||
originUrl.RawQuery != allowedURL.RawQuery {
continue
}
// return origin, true
return origin, true
}
return
}