-
Notifications
You must be signed in to change notification settings - Fork 16
/
client.go
133 lines (111 loc) · 3.8 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
133
package auctioneer
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
cfhttp "code.cloudfoundry.org/cfhttp/v2"
"code.cloudfoundry.org/lager/v3"
"code.cloudfoundry.org/tlsconfig"
"github.com/tedsuo/rata"
)
//go:generate counterfeiter -o auctioneerfakes/fake_client.go . Client
type Client interface {
RequestLRPAuctions(logger lager.Logger, traceID string, lrpStart []*LRPStartRequest) error
RequestTaskAuctions(logger lager.Logger, traceID string, tasks []*TaskStartRequest) error
}
type auctioneerClient struct {
httpClient *http.Client
insecureHTTPClient *http.Client
url string
requireTLS bool
reqGen *rata.RequestGenerator
}
func NewClient(auctioneerURL string, requestTimeout time.Duration) Client {
return &auctioneerClient{
httpClient: cfhttp.NewClient(
cfhttp.WithRequestTimeout(requestTimeout),
),
url: auctioneerURL,
reqGen: rata.NewRequestGenerator(auctioneerURL, Routes),
}
}
func NewSecureClient(auctioneerURL, caFile, certFile, keyFile string, requireTLS bool, requestTimeout time.Duration) (Client, error) {
insecureHTTPClient := cfhttp.NewClient(
cfhttp.WithRequestTimeout(requestTimeout),
)
tlsConfig, err := tlsconfig.Build(
tlsconfig.WithInternalServiceDefaults(),
tlsconfig.WithIdentityFromFile(certFile, keyFile),
).Client(tlsconfig.WithAuthorityFromFile(caFile))
if err != nil {
return nil, err
}
httpClient := cfhttp.NewClient(
cfhttp.WithRequestTimeout(requestTimeout),
cfhttp.WithTLSConfig(tlsConfig),
)
return &auctioneerClient{
httpClient: httpClient,
insecureHTTPClient: insecureHTTPClient,
url: auctioneerURL,
requireTLS: requireTLS,
reqGen: rata.NewRequestGenerator(auctioneerURL, Routes),
}, nil
}
func (c *auctioneerClient) RequestLRPAuctions(logger lager.Logger, traceID string, lrpStarts []*LRPStartRequest) error {
logger = logger.Session("request-lrp-auctions")
payload, err := json.Marshal(lrpStarts)
if err != nil {
return err
}
resp, err := c.createRequest(logger, traceID, CreateLRPAuctionsRoute, rata.Params{}, payload)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusAccepted {
return fmt.Errorf("http error: status code %d (%s)", resp.StatusCode, http.StatusText(resp.StatusCode))
}
return nil
}
func (c *auctioneerClient) RequestTaskAuctions(logger lager.Logger, traceID string, tasks []*TaskStartRequest) error {
logger = logger.Session("request-task-auctions")
payload, err := json.Marshal(tasks)
if err != nil {
return err
}
resp, err := c.createRequest(logger, traceID, CreateTaskAuctionsRoute, rata.Params{}, payload)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusAccepted {
return fmt.Errorf("http error: status code %d (%s)", resp.StatusCode, http.StatusText(resp.StatusCode))
}
return nil
}
func (c *auctioneerClient) createRequest(logger lager.Logger, traceID string, route string, params rata.Params, payload []byte) (*http.Response, error) {
resp, err := c.doRequest(c.httpClient, traceID, false, route, params, payload)
if err != nil {
// Fall back to HTTP and try again if we do not require TLS
if !c.requireTLS && c.insecureHTTPClient != nil {
logger.Error("retrying-on-http", err)
return c.doRequest(c.insecureHTTPClient, traceID, true, route, params, payload)
}
}
return resp, err
}
func (c *auctioneerClient) doRequest(client *http.Client, traceID string, useHttp bool, route string, params rata.Params, payload []byte) (*http.Response, error) {
req, err := c.reqGen.CreateRequest(route, params, bytes.NewBuffer(payload))
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Vcap-Request-Id", traceID)
if useHttp {
req.URL.Scheme = "http"
}
return client.Do(req)
}