forked from zalando/skipper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stripquery.go
111 lines (97 loc) · 2.82 KB
/
stripquery.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
// Copyright 2015 Zalando SE
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package builtin
import (
"bytes"
"fmt"
"github.com/zalando/skipper/filters"
"net/http"
"strconv"
"strings"
)
type stripQuery struct {
preserveAsHeader bool
}
// Returns a filter Spec to strip query parameters from the request and
// optionally transpose them to request headers.
//
// It always removes the query parameter from the request URL, and if the
// first filter parameter is "true", preserves the query parameter in the form
// of x-query-param-<queryParamName>: <queryParamValue> headers, so that
// ?foo=bar becomes x-query-param-foo: bar
//
// Name: "stripQuery".
func NewStripQuery() filters.Spec { return &stripQuery{} }
// "stripQuery"
func (spec *stripQuery) Name() string { return StripQueryName }
// copied from textproto/reader
func validHeaderFieldByte(b byte) bool {
return ('A' <= b && b <= 'Z') ||
('a' <= b && b <= 'z') ||
('0' <= b && b <= '9') ||
b == '-'
}
// make sure we don't generate invalid headers
func sanitize(input string) string {
toAscii := strconv.QuoteToASCII(input)
var b bytes.Buffer
for _, i := range toAscii {
if validHeaderFieldByte(byte(i)) {
b.WriteRune(i)
}
}
return b.String()
}
// Strips the query parameters and optionally preserves them in the X-Query-Param-xyz headers.
func (f *stripQuery) Request(ctx filters.FilterContext) {
r := ctx.Request()
if r == nil {
return
}
url := r.URL
if url == nil {
return
}
if !f.preserveAsHeader {
url.RawQuery = ""
return
}
q := url.Query()
for k, vv := range q {
for _, v := range vv {
if r.Header == nil {
r.Header = http.Header{}
}
r.Header.Add(fmt.Sprintf("X-Query-Param-%s", sanitize(k)), v)
}
}
url.RawQuery = ""
}
// Noop.
func (f *stripQuery) Response(ctx filters.FilterContext) {}
// Creates instances of the stripQuery filter. Accepts one optional parameter:
// "true", in order to preserve the stripped parameters in the request header.
func (mw *stripQuery) CreateFilter(config []interface{}) (filters.Filter, error) {
var preserveAsHeader = false
if len(config) == 1 {
preserveAsHeaderString, ok := config[0].(string)
if !ok {
return nil, filters.ErrInvalidFilterParameters
}
if strings.ToLower(preserveAsHeaderString) == "true" {
preserveAsHeader = true
}
}
return &stripQuery{preserveAsHeader}, nil
}