( ctx context.Context, httpReq *http.Request, res any, do func(*http.Request) (*http.Response, error), )
| 96 | } |
| 97 | |
| 98 | func httpExchange( |
| 99 | ctx context.Context, httpReq *http.Request, res any, do func(*http.Request) (*http.Response, error), |
| 100 | ) error { |
| 101 | logger := log.FromContext(ctx).WithField("url", httpReq.URL) |
| 102 | |
| 103 | logger.Debug("Send interop HTTP request") |
| 104 | httpRes, err := do(httpReq) |
| 105 | if err != nil { |
| 106 | return err |
| 107 | } |
| 108 | defer httpRes.Body.Close() |
| 109 | |
| 110 | logger = logger.WithField("http_code", httpRes.StatusCode) |
| 111 | logger.Debug("Receive interop HTTP response") |
| 112 | |
| 113 | b, err := io.ReadAll(httpRes.Body) |
| 114 | if err != nil { |
| 115 | if res == nil { |
| 116 | return nil |
| 117 | } |
| 118 | logger.WithError(err).Warn("Failed to read HTTP response body") |
| 119 | return errors.FromHTTPStatusCode(httpRes.StatusCode) |
| 120 | } |
| 121 | |
| 122 | // LoRaWAN Backend Interfaces messages are only sent with HTTP status code 200, including errors encoded in Result. |
| 123 | // Therefore, when the response status code is not 2xx, do not unmarshal the response content. |
| 124 | if httpRes.StatusCode < 200 || httpRes.StatusCode >= 300 { |
| 125 | logger.Info("Response status code does not indicate success") |
| 126 | return errors.FromHTTPStatusCode(httpRes.StatusCode) |
| 127 | } |
| 128 | |
| 129 | if err := json.Unmarshal(b, res); err != nil { |
| 130 | logger.WithError(err).Warn("Failed to decode HTTP response body") |
| 131 | return errors.FromHTTPStatusCode(httpRes.StatusCode) |
| 132 | } |
| 133 | return nil |
| 134 | } |
| 135 | |
| 136 | type joinServerHTTPClient struct { |
| 137 | clientProvider httpclient.Provider |
no test coverage detected