doRequest performs a correctly authenticated request to a specified path, and returns response body or an error object.
(ctx context.Context, method, path string, requestBody []byte)
| 71 | |
| 72 | // doRequest performs a correctly authenticated request to a specified path, and returns response body or an error object. |
| 73 | func (c *openshiftClient) doRequest(ctx context.Context, method, path string, requestBody []byte) ([]byte, error) { |
| 74 | requestURL := *c.baseURL |
| 75 | requestURL.Path = path |
| 76 | var requestBodyReader io.Reader |
| 77 | if requestBody != nil { |
| 78 | logrus.Debugf("Will send body: %s", requestBody) |
| 79 | requestBodyReader = bytes.NewReader(requestBody) |
| 80 | } |
| 81 | req, err := http.NewRequestWithContext(ctx, method, requestURL.String(), requestBodyReader) |
| 82 | if err != nil { |
| 83 | return nil, err |
| 84 | } |
| 85 | |
| 86 | if len(c.bearerToken) != 0 { |
| 87 | req.Header.Set("Authorization", "Bearer "+c.bearerToken) |
| 88 | } else if len(c.username) != 0 { |
| 89 | req.SetBasicAuth(c.username, c.password) |
| 90 | } |
| 91 | req.Header.Set("Accept", "application/json, */*") |
| 92 | req.Header.Set("User-Agent", fmt.Sprintf("skopeo/%s", version.Version)) |
| 93 | if requestBody != nil { |
| 94 | req.Header.Set("Content-Type", "application/json") |
| 95 | } |
| 96 | |
| 97 | logrus.Debugf("%s %s", method, requestURL.Redacted()) |
| 98 | res, err := c.httpClient.Do(req) |
| 99 | if err != nil { |
| 100 | return nil, err |
| 101 | } |
| 102 | defer res.Body.Close() |
| 103 | body, err := iolimits.ReadAtMost(res.Body, iolimits.MaxOpenShiftStatusBody) |
| 104 | if err != nil { |
| 105 | return nil, err |
| 106 | } |
| 107 | logrus.Debugf("Got body: %s", body) |
| 108 | // FIXME: Just throwing this useful information away only to try to guess later... |
| 109 | logrus.Debugf("Got content-type: %s", res.Header.Get("Content-Type")) |
| 110 | |
| 111 | var status status |
| 112 | statusValid := false |
| 113 | if err := json.Unmarshal(body, &status); err == nil && len(status.Status) > 0 { |
| 114 | statusValid = true |
| 115 | } |
| 116 | |
| 117 | switch { |
| 118 | case res.StatusCode == http.StatusSwitchingProtocols: // FIXME?! No idea why this weird case exists in k8s.io/kubernetes/pkg/client/restclient. |
| 119 | if statusValid && status.Status != "Success" { |
| 120 | return nil, errors.New(status.Message) |
| 121 | } |
| 122 | case res.StatusCode >= http.StatusOK && res.StatusCode <= http.StatusPartialContent: |
| 123 | // OK. |
| 124 | default: |
| 125 | if statusValid { |
| 126 | return nil, errors.New(status.Message) |
| 127 | } |
| 128 | return nil, fmt.Errorf("HTTP error: status code: %d (%s), body: %s", res.StatusCode, http.StatusText(res.StatusCode), string(body)) |
| 129 | } |
| 130 |
no test coverage detected