forked from aws/aws-sdk-go-v2
/
encode.go
144 lines (121 loc) · 3.6 KB
/
encode.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
package rest
import (
"fmt"
"io"
"net/http"
"net/url"
"github.com/aws/aws-sdk-go-v2/private/protocol"
)
// An Encoder provides encoding of REST URI path, query, and header components
// of an HTTP request. Can also encode a stream as the payload.
//
// Does not support SetFields.
type Encoder struct {
req *http.Request
path protocol.PathReplace
query url.Values
header http.Header
payload io.ReadSeeker
err error
}
// NewEncoder creates a new encoder from the passed in request. All query and
// header values will be added on top of the request's existing values. Overwriting
// duplicate values.
func NewEncoder(req *http.Request) *Encoder {
e := &Encoder{
req: req,
path: protocol.NewPathReplace(req.URL.Path),
query: req.URL.Query(),
header: req.Header,
}
return e
}
// Encode will return the request and body if one was set. If the body
// payload was not set the io.ReadSeeker will be nil.
//
// returns any error if one occured while encoding the API's parameters.
func (e *Encoder) Encode() (*http.Request, io.ReadSeeker, error) {
if e.err != nil {
return nil, nil, e.err
}
e.req.URL.Path, e.req.URL.RawPath = e.path.Encode()
e.req.URL.RawQuery = e.query.Encode()
e.req.Header = e.header
return e.req, e.payload, nil
}
// SetValue will set a value to the header, path, query.
//
// If the request's method is GET all BodyTarget values will be written to
// the query string.
func (e *Encoder) SetValue(t protocol.Target, k string, v protocol.ValueMarshaler, meta protocol.Metadata) {
if e.err != nil {
return
}
var str string
str, e.err = v.MarshalValue()
if e.err != nil {
return
}
switch t {
case protocol.HeaderTarget:
e.header.Set(k, str)
case protocol.PathTarget:
e.path.ReplaceElement(k, str)
case protocol.QueryTarget:
e.query.Set(k, str)
case protocol.BodyTarget:
if e.req.Method != "GET" {
e.err = fmt.Errorf("body target not supported for rest non-GET methods %s, %s", t, k)
return
}
e.query.Set(k, str)
default:
e.err = fmt.Errorf("unknown SetValue rest encode target, %s, %s", t, k)
}
}
// SetStream will set the stream to the payload of the request.
func (e *Encoder) SetStream(t protocol.Target, k string, v protocol.StreamMarshaler, meta protocol.Metadata) {
if e.err != nil {
return
}
switch t {
case protocol.PayloadTarget:
e.payload, e.err = v.MarshalStream()
default:
e.err = fmt.Errorf("unknown SetStream rest encode target, %s, %s", t, k)
}
}
// List will set the nested list values to the header or query.
func (e *Encoder) List(t protocol.Target, k string, meta protocol.Metadata) protocol.ListEncoder {
if e.err != nil {
return nil
}
switch t {
case protocol.QueryTarget:
return &protocol.QueryListEncoder{Key: k, Query: e.query}
case protocol.HeaderTarget:
return &protocol.HeaderListEncoder{Key: k, Header: e.header}
default:
e.err = fmt.Errorf("unknown SetList rest encode target, %s, %s", t, k)
return nil
}
}
// Map will set the nested map values to the header or query.
func (e *Encoder) Map(t protocol.Target, k string, meta protocol.Metadata) protocol.MapEncoder {
if e.err != nil {
return nil
}
switch t {
case protocol.QueryTarget:
return &protocol.QueryMapEncoder{Query: e.query}
case protocol.HeadersTarget:
return &protocol.HeaderMapEncoder{Prefix: k, Header: e.header}
default:
e.err = fmt.Errorf("unknown SetMap rest encode target, %s, %s", t, k)
return nil
}
}
// SetFields is not supported for REST encoder.
func (e *Encoder) SetFields(t protocol.Target, k string, m protocol.FieldMarshaler, meta protocol.Metadata) {
e.err = fmt.Errorf("rest encoder SetFields not supported, %s, %s", t, k)
}