/
dynamicbackendfilter.go
158 lines (140 loc) · 5.07 KB
/
dynamicbackendfilter.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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package builtin
import (
"net/url"
"github.com/zalando/skipper/filters"
)
type dynamicBackendFilterType int
const (
setDynamicBackendHostFromHeader dynamicBackendFilterType = iota
setDynamicBackendSchemeFromHeader
setDynamicBackendUrlFromHeader
setDynamicBackendHost
setDynamicBackendScheme
setDynamicBackendUrl
)
type dynamicBackendFilter struct {
typ dynamicBackendFilterType
input string
}
// verifies that the filter config has one string parameter
func dynamicBackendFilterConfig(config []interface{}) (string, error) {
if len(config) != 1 {
return "", filters.ErrInvalidFilterParameters
}
input, ok := config[0].(string)
if !ok {
return "", filters.ErrInvalidFilterParameters
}
return input, nil
}
// Returns a filter specification that is used to set dynamic backend host from a header.
// Instances expect one parameters: a header name.
// Name: "setDynamicBackendHostFromHeader".
//
// If the header exists the value is put into the `StateBag`, additionally
// `SetOutgoingHost()` is used to set the host header
func NewSetDynamicBackendHostFromHeader() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendHostFromHeader}
}
// Returns a filter specification that is used to set dynamic backend scheme from a header.
// Instances expect one parameters: a header name.
// Name: "setDynamicBackendSchemeFromHeader".
//
// If the header exists the value is put into the `StateBag`
func NewSetDynamicBackendSchemeFromHeader() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendSchemeFromHeader}
}
// Returns a filter specification that is used to set dynamic backend url from a header.
// Instances expect one parameters: a header name.
// Name: "setDynamicBackendUrlFromHeader".
//
// If the header exists the value is put into the `StateBag`, additionally
// `SetOutgoingHost()` is used to set the host header if the header is a valid url
func NewSetDynamicBackendUrlFromHeader() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendUrlFromHeader}
}
// Returns a filter specification that is used to set dynamic backend host.
// Instances expect one parameters: a host name.
// Name: "setDynamicBackendHost".
//
// The value is put into the `StateBag`, additionally
// `SetOutgoingHost()` is used to set the host header
func NewSetDynamicBackendHost() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendHost}
}
// Returns a filter specification that is used to set dynamic backend scheme.
// Instances expect one parameters: a scheme name.
// Name: "setDynamicBackendScheme".
//
// The value is put into the `StateBag`
func NewSetDynamicBackendScheme() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendScheme}
}
// Returns a filter specification that is used to set dynamic backend url.
// Instances expect one parameters: a url.
// Name: "setDynamicBackendUrl".
//
// The value is put into the `StateBag`, additionally `SetOutgoingHost()`
// is used to set the host header if the input provided is a valid url
func NewSetDynamicBackendUrl() filters.Spec {
return &dynamicBackendFilter{typ: setDynamicBackendUrl}
}
func (spec *dynamicBackendFilter) Name() string {
switch spec.typ {
case setDynamicBackendHostFromHeader:
return filters.SetDynamicBackendHostFromHeader
case setDynamicBackendSchemeFromHeader:
return filters.SetDynamicBackendSchemeFromHeader
case setDynamicBackendUrlFromHeader:
return filters.SetDynamicBackendUrlFromHeader
case setDynamicBackendHost:
return filters.SetDynamicBackendHost
case setDynamicBackendScheme:
return filters.SetDynamicBackendScheme
case setDynamicBackendUrl:
return filters.SetDynamicBackendUrl
default:
panic("invalid type")
}
}
//lint:ignore ST1016 "spec" makes sense here and we reuse the type for the filter
func (spec *dynamicBackendFilter) CreateFilter(config []interface{}) (filters.Filter, error) {
input, err := dynamicBackendFilterConfig(config)
return &dynamicBackendFilter{typ: spec.typ, input: input}, err
}
func (f *dynamicBackendFilter) Request(ctx filters.FilterContext) {
switch f.typ {
case setDynamicBackendHostFromHeader:
header := ctx.Request().Header.Get(f.input)
if header != "" {
ctx.StateBag()[filters.DynamicBackendHostKey] = header
ctx.SetOutgoingHost(header)
}
case setDynamicBackendSchemeFromHeader:
header := ctx.Request().Header.Get(f.input)
if header != "" {
ctx.StateBag()[filters.DynamicBackendSchemeKey] = header
}
case setDynamicBackendUrlFromHeader:
header := ctx.Request().Header.Get(f.input)
if header != "" {
ctx.StateBag()[filters.DynamicBackendURLKey] = header
bu, err := url.ParseRequestURI(header)
if err == nil {
ctx.SetOutgoingHost(bu.Host)
}
}
case setDynamicBackendHost:
ctx.StateBag()[filters.DynamicBackendHostKey] = f.input
ctx.SetOutgoingHost(f.input)
case setDynamicBackendScheme:
ctx.StateBag()[filters.DynamicBackendSchemeKey] = f.input
case setDynamicBackendUrl:
ctx.StateBag()[filters.DynamicBackendURLKey] = f.input
bu, err := url.ParseRequestURI(f.input)
if err == nil {
ctx.SetOutgoingHost(bu.Host)
}
}
}
func (f *dynamicBackendFilter) Response(ctx filters.FilterContext) {}