Я хочу реализовать пользовательский http.Transport
для стандартного http.Client
, который будет автоматически повторять попытку, если клиент получил тайм-аут.
PS по какой-то причине пользовательский http.Transport
является должен -иметь . Я уже проверил hashicorp / go -retryablehttp , однако он не позволит мне использовать мой собственный http.Transport
.
Вот мои попытки, пользовательский компонент:
type CustomTransport struct {
http.RoundTripper
// ... private fields
}
func NewCustomTransport(upstream *http.Transport) *CustomTransport {
upstream.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
// ... other customizations for transport
return &CustomTransport{upstream}
}
func (ct *CustomTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
req.Header.Set("Secret", "Blah blah blah")
// ... other customizations for each request
for i := 1; i <= 5; i++ {
resp, err = ct.RoundTripper.RoundTrip(req)
if errors.Is(err, context.DeadlineExceeded) {
log.Warnf("#%d got timeout will retry - %v", i, err)
//time.Sleep(time.Duration(100*i) * time.Millisecond)
continue
} else {
break
}
}
log.Debugf("got final result: %v", err)
return resp, err
}
Код вызывающего абонента:
func main() {
transport := NewCustomTransport(http.DefaultTransport.(*http.Transport))
client := &http.Client{
Timeout: 8 * time.Second,
Transport: transport,
}
apiUrl := "https://httpbin.org/delay/10"
log.Debugf("begin to get %q", apiUrl)
start := time.Now()
resp, err := client.Get(apiUrl)
if err != nil {
log.Warnf("client got error: %v", err)
} else {
defer resp.Body.Close()
}
log.Debugf("end to get %q, time cost: %v", apiUrl, time.Since(start))
if resp != nil {
data, err := httputil.DumpResponse(resp, true)
if err != nil {
log.Warnf("fail to dump resp: %v", err)
}
fmt.Println(string(data))
}
}
Мои реализации работают не так, как ожидалось, после истечения тайм-аута клиента повторная попытка фактически не произойдет. См. Журнал ниже:
2020-07-15T00:53:22.586 DEBUG begin to get "https://httpbin.org/delay/10"
2020-07-15T00:53:30.590 WARN #1 got timeout will retry - context deadline exceeded
2020-07-15T00:53:30.590 WARN #2 got timeout will retry - context deadline exceeded
2020-07-15T00:53:30.590 WARN #3 got timeout will retry - context deadline exceeded
2020-07-15T00:53:30.590 WARN #4 got timeout will retry - context deadline exceeded
2020-07-15T00:53:30.590 WARN #5 got timeout will retry - context deadline exceeded
2020-07-15T00:53:30.590 DEBUG got final result: context deadline exceeded
2020-07-15T00:53:30.590 WARN client got error: Get "https://httpbin.org/delay/10": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
2020-07-15T00:53:30.590 DEBUG end to get "https://httpbin.org/delay/10", time cost: 8.004182786s
Не могли бы вы рассказать мне, как это исправить, или какие-либо методы / идеи для реализации такого http.Client
?