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 }