forked from badboyd/lura
/
request.go
93 lines (84 loc) · 2.27 KB
/
request.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
// SPDX-License-Identifier: Apache-2.0
package proxy
import (
"bytes"
"io"
"io/ioutil"
"net/url"
)
// Request contains the data to send to the backend
type Request struct {
Method string
URL *url.URL
Query url.Values
Path string
Body io.ReadCloser
Params map[string]string
Headers map[string][]string
}
// GeneratePath takes a pattern and updates the path of the request
func (r *Request) GeneratePath(URLPattern string) {
if len(r.Params) == 0 {
r.Path = URLPattern
return
}
buff := []byte(URLPattern)
for k, v := range r.Params {
key := []byte{}
key = append(key, "{{."...)
key = append(key, k...)
key = append(key, "}}"...)
buff = bytes.Replace(buff, key, []byte(v), -1)
}
r.Path = string(buff)
}
// Clone clones itself into a new request. The returned cloned request is not
// thread-safe, so changes on request.Params and request.Headers could generate
// race-conditions depending on the part of the pipe they are being executed.
// For thread-safe request headers and/or params manipulation, use the proxy.CloneRequest
// function.
func (r *Request) Clone() Request {
return Request{
Method: r.Method,
URL: r.URL,
Query: r.Query,
Path: r.Path,
Body: r.Body,
Params: r.Params,
Headers: r.Headers,
}
}
// CloneRequest returns a deep copy of the received request, so the received and the
// returned proxy.Request do not share a pointer
func CloneRequest(r *Request) *Request {
clone := r.Clone()
clone.Headers = CloneRequestHeaders(r.Headers)
clone.Params = CloneRequestParams(r.Params)
if r.Body == nil {
return &clone
}
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
r.Body.Close()
r.Body = ioutil.NopCloser(bytes.NewReader(buf.Bytes()))
clone.Body = ioutil.NopCloser(buf)
return &clone
}
// CloneRequestHeaders returns a copy of the received request headers
func CloneRequestHeaders(headers map[string][]string) map[string][]string {
m := make(map[string][]string, len(headers))
for k, vs := range headers {
tmp := make([]string, len(vs))
copy(tmp, vs)
m[k] = tmp
}
return m
}
// CloneRequestParams returns a copy of the received request params
func CloneRequestParams(params map[string]string) map[string]string {
m := make(map[string]string, len(params))
for k, v := range params {
m[k] = v
}
return m
}