@@ -34,7 +34,6 @@ import (
3434 "context"
3535 "errors"
3636 "fmt"
37- "github.com/hashicorp/errwrap"
3837 "github.com/hashicorp/terraform-plugin-sdk/helper/resource"
3938 "google.golang.org/api/googleapi"
4039 "io/ioutil"
@@ -99,19 +98,29 @@ func (t *retryTransport) RoundTrip(req *http.Request) (resp *http.Response, resp
9998 backoff := time .Millisecond * 500
10099 nextBackoff := time .Millisecond * 500
101100
101+ // VCR depends on the original request body being consumed, so
102+ // consume here. Since this won't affect the request itself,
103+ // we do this before the actual Retry loop so we can consume the request Body as needed
104+ // e.g. if the request couldn't be retried, we use the original request
105+ if _ , err := httputil .DumpRequestOut (req , true ); err != nil {
106+ log .Printf ("[WARN] Retry Transport: Consuming original request body failed: %v" , err )
107+ }
108+
102109 log .Printf ("[DEBUG] Retry Transport: starting RoundTrip retry loop" )
103110Retry:
104111 for {
105- log .Printf ("[DEBUG] Retry Transport: request attempt %d" , attempts )
106-
107- // Copy the request - we dont want to use the original request as
108- // RoundTrip contract says request body can/will be consumed
112+ // RoundTrip contract says request body can/will be consumed, so we need to
113+ // copy the request body for each attempt.
114+ // If we can't copy the request, we run as a single request.
109115 newRequest , copyErr := copyHttpRequest (req )
110116 if copyErr != nil {
111- respErr = errwrap .Wrapf ("unable to copy invalid http.Request for retry: {{err}}" , copyErr )
117+ log .Printf ("[WARN] Retry Transport: Unable to copy request body: %v." , copyErr )
118+ log .Printf ("[WARN] Retry Transport: Running request as non-retryable" )
119+ resp , respErr = t .internal .RoundTrip (req )
112120 break Retry
113121 }
114122
123+ log .Printf ("[DEBUG] Retry Transport: request attempt %d" , attempts )
115124 // Do the wrapped Roundtrip. This is one request in the retry loop.
116125 resp , respErr = t .internal .RoundTrip (newRequest )
117126 attempts ++
@@ -141,13 +150,6 @@ Retry:
141150 continue
142151 }
143152 }
144-
145- // VCR depends on the original request body being consumed, so consume it here
146- _ , err := httputil .DumpRequestOut (req , true )
147- if err != nil {
148- log .Printf ("[DEBUG] Retry Transport: Reading request failed: %v" , err )
149- }
150-
151153 log .Printf ("[DEBUG] Retry Transport: Returning after %d attempts" , attempts )
152154 return resp , respErr
153155}
@@ -157,15 +159,13 @@ Retry:
157159// so it can be consumed.
158160func copyHttpRequest (req * http.Request ) (* http.Request , error ) {
159161 newRequest := * req
160-
161162 if req .Body == nil || req .Body == http .NoBody {
162163 return & newRequest , nil
163164 }
164-
165165 // Helpers like http.NewRequest add a GetBody for copying.
166166 // If not given, we should reject the request.
167167 if req .GetBody == nil {
168- return nil , errors .New ("invalid HTTP request for transport, expected request.GetBody for non-empty Body" )
168+ return nil , errors .New ("request.GetBody is not defined for non-empty Body" )
169169 }
170170
171171 bd , err := req .GetBody ()
0 commit comments