-
Notifications
You must be signed in to change notification settings - Fork 7
/
client.go
132 lines (101 loc) · 2.78 KB
/
client.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
package eth2api
import (
"context"
"fmt"
)
type Client interface {
Request(ctx context.Context, req PreparedRequest) Response
}
// simplified Query interface. No duplicate key entries
type Query map[string]interface{}
type PreparedRequest interface {
// The type of request
Method() ReqMethod
// Body, optional. Returns nil if no body. Only used for PUT/POST methods.
Body() interface{}
// Path to request, including any path variable contents
Path() string
// Query params to add to the request, may be nil
Query() Query
}
type Response interface {
// Decode into destination type. May throw a decoding error.
// Or throws DecodeNoContentErr if it was an error without returned value.
// Call with nil to just close the response contents.
// May only be called once.
Decode(dest interface{}) (code uint, err error)
// TODO: maybe expose headers?
}
type fullReq struct {
method ReqMethod
path string
body interface{}
query Query
}
func (p *fullReq) Method() ReqMethod {
return p.method
}
func (p *fullReq) Body() interface{} {
return p.body
}
func (p *fullReq) Path() string {
return p.path
}
func (p *fullReq) Query() Query {
return p.query
}
type PlainGET string
func (p PlainGET) Method() ReqMethod {
return GET
}
func (p PlainGET) Body() interface{} {
return nil
}
func (p PlainGET) Path() string {
return string(p)
}
func (p PlainGET) Query() Query {
return nil
}
func FmtGET(format string, data ...interface{}) PreparedRequest {
return PlainGET(fmt.Sprintf(format, data...))
}
func QueryGET(query Query, path string) PreparedRequest {
return &fullReq{method: GET, path: path, body: nil, query: query}
}
func FmtQueryGET(query Query, format string, data ...interface{}) PreparedRequest {
return &fullReq{method: GET, path: fmt.Sprintf(format, data...), body: nil, query: query}
}
func BodyPOST(path string, body interface{}) PreparedRequest {
return &fullReq{method: POST, path: path, body: body, query: nil}
}
func SimpleRequest(ctx context.Context, cli Client, req PreparedRequest, dest interface{}) (exists bool, err error) {
resp := cli.Request(ctx, req)
code, err := resp.Decode(dest)
if code == 404 {
return false, nil
} else {
return true, err
}
}
func MinimalRequest(ctx context.Context, cli Client, req PreparedRequest, dest interface{}) (err error) {
resp := cli.Request(ctx, req)
_, err = resp.Decode(dest)
return
}
type ClientFunc func(ctx context.Context, req PreparedRequest) Response
func (fn ClientFunc) Request(ctx context.Context, req PreparedRequest) Response {
return fn(ctx, req)
}
type ClientApiErr struct {
error
}
func (ce ClientApiErr) Code() uint {
return 400
}
type ClientErr struct {
error
}
func (ce ClientErr) Decode(dest interface{}) (uint, error) {
return 0, fmt.Errorf("client usage error, cannot decode: %w", ce.error)
}