diff --git a/internal/cmd/http.go b/internal/cmd/http.go index 4f624be..bb1b525 100644 --- a/internal/cmd/http.go +++ b/internal/cmd/http.go @@ -44,7 +44,7 @@ func (c *HttpCommand) http() error { url, getData(result.body)) if err != nil { - log.Errorf("Request error: %v\n", err) + log.Fatalf("Request error: %v\n", err) } req.Header = result.headers if len(*result.urlValues) > 0 { diff --git a/internal/env/run.go b/internal/env/run.go index a7d690b..115cc86 100644 --- a/internal/env/run.go +++ b/internal/env/run.go @@ -77,7 +77,10 @@ func call(m *parser.Method, err error) error { var any common.Input for err == nil { err = input.Decode(&any) - if err == io.EOF { + if err != nil { + if err == io.EOF { + err = nil + } break } err = env.Exec(m, &any) diff --git a/internal/utils/retry_cli.go b/internal/utils/retry_cli.go index a11bf64..6d013c9 100644 --- a/internal/utils/retry_cli.go +++ b/internal/utils/retry_cli.go @@ -80,10 +80,20 @@ func (c *Client) RetriableDo(req *http.Request) (*http.Response, error) { logger.HttpRequest(req) var i int64 for { + if i > 0 && req.GetBody != nil { + body, err := req.GetBody() + if err != nil { + return nil, err + } + req.Body = body + } // #nosec G704 -- request target is intentionally provided by CLI input. resp, err := c.HttpClient.Do(req) if c.RetryWithBackoff(logger, i, resp, err) { logger.Debugf("%d/%d\n", i, c.MaxRetry) + if resp != nil && resp.Body != nil { + _ = resp.Body.Close() + } i++ } else { return resp, err @@ -97,23 +107,27 @@ func (c *Client) RetriableDo(req *http.Request) (*http.Response, error) { func (c *Client) RetryWithBackoff(logger *config.Log, i int64, resp *http.Response, err error) bool { doRetry := false + statusCode := 0 retrySeconds := time.Second * time.Duration(i) + if resp != nil { + statusCode = resp.StatusCode + } if err != nil { logger.Errorf("error = %v, retriable.\n", err) doRetry = true - } else if resp.StatusCode == 0 || resp.StatusCode > 500 { - logger.Debugf("status = %d, retriable.\n", resp.StatusCode) + } else if statusCode == 0 || statusCode >= 500 { + logger.Debugf("status = %d, retriable.\n", statusCode) doRetry = true - } else if resp.StatusCode == 429 { + } else if statusCode == 429 { doRetry = true retrySeconds = time.Duration(getRetryAfterHeaderValue(resp)) logger.Debugf( "status = %d, retry_after = %d seconds, retriable.\n", - resp.StatusCode, retrySeconds) - } else if c.StatusCode > 0 && resp.StatusCode != c.StatusCode { + statusCode, retrySeconds) + } else if c.StatusCode > 0 && statusCode != c.StatusCode { // allow for an override to wait for a specific code doRetry = true - logger.Debugf("status = %d, retrying till %d.\n", resp.StatusCode, c.StatusCode) + logger.Debugf("status = %d, retrying till %d.\n", statusCode, c.StatusCode) } if doRetry && i < c.MaxRetry { time.Sleep(retrySeconds) @@ -126,6 +140,9 @@ func (c *Client) RetryWithBackoff(logger *config.Log, // default to DefaultRetryAfterSeconds if not present or invalid func getRetryAfterHeaderValue(resp *http.Response) time.Duration { retryAfter := DefaultRetryAfterSeconds + if resp == nil { + return retryAfter + } var err error var i int if val, ok := resp.Header[RetryAfter]; ok {