-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
common_http.go
88 lines (76 loc) · 2.33 KB
/
common_http.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
package pipeline
import (
"bytes"
"context"
"encoding/json"
"io"
"net/http"
"time"
"github.com/pkg/errors"
"github.com/smartcontractkit/chainlink/core/logger"
"github.com/smartcontractkit/chainlink/core/utils"
)
func makeHTTPRequest(
ctx context.Context,
lggr logger.Logger,
method StringParam,
url URLParam,
requestData MapParam,
allowUnrestrictedNetworkAccess BoolParam,
cfg Config,
) ([]byte, int, http.Header, time.Duration, error) {
var bodyReader io.Reader
if requestData != nil {
bodyBytes, err := json.Marshal(requestData)
if err != nil {
return nil, 0, nil, 0, errors.Wrap(err, "failed to encode request body as JSON")
}
bodyReader = bytes.NewReader(bodyBytes)
}
timeoutCtx, cancel := context.WithTimeout(ctx, cfg.DefaultHTTPTimeout().Duration())
defer cancel()
request, err := http.NewRequestWithContext(timeoutCtx, string(method), url.String(), bodyReader)
if err != nil {
return nil, 0, nil, 0, errors.Wrap(err, "failed to create http.Request")
}
request.Header.Set("Content-Type", "application/json")
httpRequest := utils.HTTPRequest{
Request: request,
Config: utils.HTTPRequestConfig{
SizeLimit: cfg.DefaultHTTPLimit(),
AllowUnrestrictedNetworkAccess: bool(allowUnrestrictedNetworkAccess),
},
Logger: lggr.Named("HTTPRequest"),
}
start := time.Now()
responseBytes, statusCode, headers, err := httpRequest.SendRequest()
if ctx.Err() != nil {
return nil, 0, nil, 0, errors.New("http request timed out or interrupted")
}
if err != nil {
return nil, 0, nil, 0, errors.Wrapf(err, "error making http request")
}
elapsed := time.Since(start) // TODO: return elapsed from utils/http
if statusCode >= 400 {
maybeErr := bestEffortExtractError(responseBytes)
return nil, statusCode, headers, 0, errors.Errorf("got error from %s: (status code %v) %s", url.String(), statusCode, maybeErr)
}
return responseBytes, statusCode, headers, elapsed, nil
}
type PossibleErrorResponses struct {
Error string `json:"error"`
ErrorMessage string `json:"errorMessage"`
}
func bestEffortExtractError(responseBytes []byte) string {
var resp PossibleErrorResponses
err := json.Unmarshal(responseBytes, &resp)
if err != nil {
return ""
}
if resp.Error != "" {
return resp.Error
} else if resp.ErrorMessage != "" {
return resp.ErrorMessage
}
return string(responseBytes)
}