github.com/qiniu/go-sdk/v7@v7.27.0/internal/clientv2/interceptor_retry_hosts_test.go (about)

     1  //go:build unit
     2  // +build unit
     3  
     4  package clientv2
     5  
     6  import (
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"strings"
    10  	"testing"
    11  	"time"
    12  
    13  	clientV1 "github.com/qiniu/go-sdk/v7/client"
    14  	"github.com/qiniu/go-sdk/v7/internal/hostprovider"
    15  )
    16  
    17  func TestHostsAlwaysRetryInterceptor(t *testing.T) {
    18  	clientV1.DebugMode = true
    19  	defer func() {
    20  		clientV1.DebugMode = false
    21  	}()
    22  
    23  	hostA := "aaa.aa.com"
    24  	hostB := "bbb.bb.com"
    25  	hRetryMax := 2
    26  	hRetryInterceptor := NewHostsRetryInterceptor(HostsRetryConfig{
    27  		RetryMax: hRetryMax,
    28  		ShouldRetry: func(req *http.Request, resp *http.Response, err error) bool {
    29  			return true
    30  		},
    31  		ShouldFreezeHost:   nil,
    32  		HostFreezeDuration: 0,
    33  		HostProvider:       hostprovider.NewWithHosts([]string{hostA, hostB}),
    34  	})
    35  
    36  	retryMax := 1
    37  	sRetryInterceptor := NewSimpleRetryInterceptor(SimpleRetryConfig{
    38  		RetryMax: retryMax,
    39  		RetryInterval: func() time.Duration {
    40  			return time.Second
    41  		},
    42  		ShouldRetry: func(req *http.Request, resp *http.Response, err error) bool {
    43  			return true
    44  		},
    45  	})
    46  
    47  	doCount := 0
    48  	interceptor := NewSimpleInterceptor(func(req *http.Request, handler Handler) (*http.Response, error) {
    49  		doCount += 1
    50  
    51  		value := req.Header.Get(headerKey)
    52  		value += " -> request"
    53  		req.Header.Set(headerKey, value)
    54  
    55  		resp, err := handler(req)
    56  
    57  		value = resp.Header.Get(headerKey)
    58  		value += " -> response"
    59  		resp.Header.Set(headerKey, value)
    60  		return resp, err
    61  	})
    62  
    63  	c := NewClient(&testClient{}, interceptor, hRetryInterceptor, sRetryInterceptor)
    64  
    65  	resp, _ := Do(c, RequestParams{
    66  		Context: nil,
    67  		Method:  RequestMethodGet,
    68  		Url:     "https://" + hostA + "/path/123",
    69  		Header:  nil,
    70  		GetBody: nil,
    71  	})
    72  
    73  	if (retryMax+1)*2 != doCount {
    74  		t.Fatalf("retry count is not error:%d", doCount)
    75  	}
    76  
    77  	value := resp.Header.Get(headerKey)
    78  	if value != " -> request -> Do -> response" {
    79  		t.Fatalf("retry flow error")
    80  	}
    81  
    82  	if resp.Request.Host != hostB {
    83  		t.Fatalf("retry host set error")
    84  	}
    85  }
    86  
    87  func TestHostsNotRetryInterceptor(t *testing.T) {
    88  	clientV1.DebugMode = true
    89  	defer func() {
    90  		clientV1.DebugMode = false
    91  	}()
    92  
    93  	hostA := "aaa.aa.com"
    94  	hostB := "bbb.bb.com"
    95  	hRetryMax := 2
    96  	hRetryInterceptor := NewHostsRetryInterceptor(HostsRetryConfig{
    97  		RetryMax:           hRetryMax,
    98  		ShouldFreezeHost:   nil,
    99  		HostFreezeDuration: 0,
   100  		HostProvider:       hostprovider.NewWithHosts([]string{hostA, hostB}),
   101  	})
   102  
   103  	retryMax := 1
   104  	sRetryInterceptor := NewSimpleRetryInterceptor(SimpleRetryConfig{
   105  		RetryMax: retryMax,
   106  		RetryInterval: func() time.Duration {
   107  			return time.Second
   108  		},
   109  	})
   110  
   111  	doCount := 0
   112  	interceptor := NewSimpleInterceptor(func(req *http.Request, handler Handler) (*http.Response, error) {
   113  		doCount += 1
   114  
   115  		value := req.Header.Get(headerKey)
   116  		value += " -> request"
   117  		req.Header.Set(headerKey, value)
   118  
   119  		resp, err := handler(req)
   120  
   121  		value = resp.Header.Get(headerKey)
   122  		value += " -> response"
   123  		resp.Header.Set(headerKey, value)
   124  		return resp, err
   125  	})
   126  
   127  	c := NewClient(&testClient{statusCode: 400}, interceptor, hRetryInterceptor, sRetryInterceptor)
   128  
   129  	start := time.Now()
   130  
   131  	resp, _ := Do(c, RequestParams{
   132  		Context: nil,
   133  		Method:  RequestMethodGet,
   134  		Url:     "https://" + hostA + "/path/123",
   135  		Header:  nil,
   136  		GetBody: nil,
   137  	})
   138  	duration := time.Since(start)
   139  
   140  	if d := duration - time.Duration(doCount-1)*time.Second; d >= 900*time.Millisecond || d <= -900*time.Millisecond {
   141  		t.Fatalf("retry interval may be error")
   142  	}
   143  
   144  	if 1 != doCount {
   145  		t.Fatalf("retry count is not error:%d", doCount)
   146  	}
   147  
   148  	value := resp.Header.Get(headerKey)
   149  	if value != " -> request -> Do -> response" {
   150  		t.Fatalf("retry flow error")
   151  	}
   152  
   153  	if resp.Request.Host != hostA {
   154  		t.Fatalf("retry host set error")
   155  	}
   156  }
   157  
   158  func TestHostsRetryInterceptorByRequest(t *testing.T) {
   159  	serveMux_1 := http.NewServeMux()
   160  	serveMux_1.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   161  		w.WriteHeader(599)
   162  		w.Write([]byte(`{"error":"test error"}`))
   163  	})
   164  	server_1 := httptest.NewServer(serveMux_1)
   165  	defer server_1.Close()
   166  
   167  	serveMux_2 := http.NewServeMux()
   168  	serveMux_2.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
   169  		w.WriteHeader(http.StatusOK)
   170  	})
   171  	server_2 := httptest.NewServer(serveMux_2)
   172  	defer server_2.Close()
   173  
   174  	hRetryMax := 30
   175  	hRetryInterceptor := NewHostsRetryInterceptor(HostsRetryConfig{
   176  		RetryMax: hRetryMax,
   177  		HostProvider: hostprovider.NewWithHosts([]string{
   178  			strings.TrimPrefix(server_1.URL, "http://"),
   179  			strings.TrimPrefix(server_2.URL, "http://"),
   180  		}),
   181  	})
   182  
   183  	retryMax := 1
   184  	sRetryInterceptor := NewSimpleRetryInterceptor(SimpleRetryConfig{
   185  		RetryMax: retryMax,
   186  		RetryInterval: func() time.Duration {
   187  			return time.Second
   188  		},
   189  	})
   190  
   191  	doCount := 0
   192  	interceptor := NewSimpleInterceptor(func(req *http.Request, handler Handler) (*http.Response, error) {
   193  		doCount += 1
   194  
   195  		value := req.Header.Get(headerKey)
   196  		value += " -> request"
   197  		req.Header.Set(headerKey, value)
   198  
   199  		resp, err := handler(req)
   200  		if err != nil || resp == nil {
   201  			return nil, err
   202  		}
   203  
   204  		value = resp.Header.Get(headerKey)
   205  		value += " -> response"
   206  		resp.Header.Set(headerKey, value)
   207  		return resp, err
   208  	})
   209  
   210  	c := NewClient(nil, interceptor, hRetryInterceptor, sRetryInterceptor)
   211  	resp, err := Do(c, RequestParams{
   212  		Context: nil,
   213  		Method:  RequestMethodGet,
   214  		Url:     server_1.URL,
   215  		Header:  nil,
   216  		GetBody: nil,
   217  	})
   218  	if err != nil {
   219  		t.Fatalf("request should success:%v", err)
   220  	}
   221  
   222  	if (retryMax+1)+1 != doCount {
   223  		t.Fatalf("retry count is not error:%d", doCount)
   224  	}
   225  
   226  	value := resp.Header.Get(headerKey)
   227  	if value != " -> response" {
   228  		t.Fatalf("retry flow error")
   229  	}
   230  
   231  	if resp.Request.Host != strings.TrimPrefix(server_2.URL, "http://") {
   232  		t.Fatalf("retry host set error")
   233  	}
   234  }