-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrules.go
116 lines (100 loc) · 2.55 KB
/
rules.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"fmt"
"net/http"
"regexp"
"strings"
)
type Rule struct {
Match map[string]*regexp.Regexp
Mutations []Mutation
FrontendKey string
FrontendConfig *FrontendConfig
FrontendHandler http.Handler
}
func (rule *Rule) Check(r *http.Request) bool {
for name, rx := range rule.Match {
var values []string
switch {
case strings.EqualFold(name, "host"):
values = []string{r.Host}
case strings.EqualFold(name, "method"):
values = []string{r.Method}
case strings.EqualFold(name, "path"):
values = []string{r.URL.Path}
default:
values = r.Header.Values(name)
}
any := false
for _, value := range values {
if rx.MatchString(value) {
any = true
break
}
}
if !any {
return false
}
}
return true
}
func (rule *Rule) IsTerminal() bool {
return rule.FrontendKey != ""
}
func (rule *Rule) ApplyFirst(w http.ResponseWriter, r *http.Request) {
for _, mutation := range rule.Mutations {
mutation.ApplyFirst(w, r)
}
}
func (rule *Rule) ApplyPre(w http.ResponseWriter, r *http.Request) {
for _, mutation := range rule.Mutations {
mutation.ApplyPre(w, r)
}
}
func (rule *Rule) ApplyPost(w http.ResponseWriter, r *http.Request) {
for _, mutation := range rule.Mutations {
mutation.ApplyPost(w, r)
}
}
func CompileRule(impl *Impl, cfg *RuleConfig) (*Rule, error) {
var err error
out := new(Rule)
if len(cfg.Match) != 0 {
out.Match = make(map[string]*regexp.Regexp, len(cfg.Match))
for name, pattern := range cfg.Match {
out.Match[name], err = regexp.Compile(`^` + pattern + `$`)
if err != nil {
return nil, fmt.Errorf("match[%q]: failed to compile regex /^%s$/: %w", name, pattern, err)
}
}
}
out.Mutations = make([]Mutation, len(cfg.Mutations))
for i, mutcfg := range cfg.Mutations {
out.Mutations[i], err = CompileMutation(mutcfg)
if err != nil {
return nil, fmt.Errorf("mutations[%d]: %w", i, err)
}
}
out.FrontendKey = cfg.Frontend
switch {
case out.FrontendKey == "":
// pass
case strings.HasPrefix(out.FrontendKey, "ERROR:"):
out.FrontendHandler, err = CompileErrorHandler(impl, out.FrontendKey)
if err != nil {
return nil, err
}
case strings.HasPrefix(out.FrontendKey, "REDIR:"):
out.FrontendHandler, err = CompileRedirHandler(impl, out.FrontendKey)
if err != nil {
return nil, err
}
default:
out.FrontendConfig = impl.cfg.Frontends[out.FrontendKey]
out.FrontendHandler = impl.frontends[out.FrontendKey]
if out.FrontendHandler == nil {
return nil, fmt.Errorf("unknown frontend %q", out.FrontendKey)
}
}
return out, nil
}