-
Notifications
You must be signed in to change notification settings - Fork 0
/
client.go
118 lines (95 loc) · 3.56 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
package httpclient
import (
"context"
"net/http"
)
//go:generate mockgen -destination=mocks/client.go -package=mocks github.com/phamvinhdat/httpclient Client
type Client interface {
Get(ctx context.Context, url string, opts ...RequestOption) (int, error)
Head(ctx context.Context, url string, opts ...RequestOption) (int, error)
Post(ctx context.Context, url string, opts ...RequestOption) (int, error)
Put(ctx context.Context, url string, opts ...RequestOption) (int, error)
Patch(ctx context.Context, url string, opts ...RequestOption) (int, error)
Delete(ctx context.Context, url string, opts ...RequestOption) (int, error)
Connect(ctx context.Context, url string, opts ...RequestOption) (int, error)
Options(ctx context.Context, url string, opts ...RequestOption) (int, error)
Trace(ctx context.Context, url string, opts ...RequestOption) (int, error)
}
type RequestHookFn func(context.Context, *http.Request) error
type ResponseHookFn func(context.Context, *http.Response) error
type HookFn func(ctx context.Context, reqChain Chain) (*http.Response, error)
type client struct {
sender Sender
header http.Header
hookFns []HookFn
}
func NewClient(opts ...ClientOption) Client {
opt := getClientOption(opts...)
return &client{
sender: opt.sender,
header: opt.header,
hookFns: opt.hookFns,
}
}
func (c *client) Get(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodGet, opts...)
}
func (c *client) Head(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodHead, opts...)
}
func (c *client) Post(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodPost, opts...)
}
func (c *client) Put(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodPut, opts...)
}
func (c *client) Patch(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodPatch, opts...)
}
func (c *client) Delete(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodDelete, opts...)
}
func (c *client) Connect(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodConnect, opts...)
}
func (c *client) Options(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodOptions, opts...)
}
func (c *client) Trace(ctx context.Context, url string, opts ...RequestOption) (int, error) {
return c.execute(ctx, url, http.MethodTrace, opts...)
}
func (c *client) execute(ctx context.Context, url, method string,
opts ...RequestOption) (int, error) {
// get requestOption
opt := getRequestOption(opts...)
// convert to http.Request
req, err := c.buildHttpRequest(ctx, url, method, opt)
if err != nil {
return 0, err
}
// send request
res, err := c.proceed(ctx, req, opt)
if err != nil {
return 0, err
}
defer func() {
_ = res.Body.Close()
}()
return res.StatusCode, nil
}
func (c *client) proceed(ctx context.Context, req *http.Request,
opt requestOption) (*http.Response, error) {
hookFns := append(opt.hookFns, sendingRequestHook(c.sender))
reqChain := &chain{
index: 0,
req: req,
hookFns: append(c.hookFns, hookFns...),
}
return reqChain.Proceed(ctx, req)
}
func sendingRequestHook(sender Sender) HookFn {
return func(ctx context.Context, reqChain Chain) (*http.Response, error) {
req := reqChain.GetRequest(ctx)
return sender.Send(ctx, req)
}
}