github.com/qiniu/go-sdk/v7@v7.27.0/internal/clientv2/client.go (about) 1 package clientv2 2 3 import ( 4 "net/http" 5 "reflect" 6 "sort" 7 "sync" 8 9 clientV1 "github.com/qiniu/go-sdk/v7/client" 10 internal_io "github.com/qiniu/go-sdk/v7/internal/io" 11 ) 12 13 type Client interface { 14 Do(req *http.Request) (*http.Response, error) 15 } 16 17 type Handler func(req *http.Request) (*http.Response, error) 18 19 type client struct { 20 coreClient Client 21 interceptors interceptorList 22 interceptorsMutex sync.RWMutex 23 } 24 25 func NewClient(cli Client, interceptors ...Interceptor) Client { 26 if cli == nil { 27 cli = NewClientWithClientV1(&clientV1.DefaultClient) 28 } 29 30 var is interceptorList = interceptors 31 is = append(is, newDefaultHeaderInterceptor()) 32 is = append(is, newDebugInterceptor()) 33 34 if c, ok := cli.(*client); ok { 35 c.addInterceptors(is) 36 return c 37 } 38 39 sort.Sort(is) 40 return &client{ 41 coreClient: cli, 42 interceptors: is, 43 } 44 } 45 46 func (c *client) addInterceptors(is interceptorList) { 47 c.interceptorsMutex.Lock() 48 defer c.interceptorsMutex.Unlock() 49 50 for _, i := range is { 51 c.addInterceptor(i) 52 } 53 sort.Sort(c.interceptors) 54 } 55 56 func (c *client) addInterceptor(interceptor Interceptor) { 57 for _, i := range c.interceptors { 58 if reflect.TypeOf(i) == reflect.TypeOf(interceptor) { 59 return 60 } 61 } 62 c.interceptors = append(c.interceptors, interceptor) 63 } 64 65 func (c *client) mergeInterceptors(req *http.Request) interceptorList { 66 c.interceptorsMutex.RLock() 67 defer c.interceptorsMutex.RUnlock() 68 69 intercetorsFromRequest := getIntercetorsFromRequest(req) 70 newInterceptorList := make(interceptorList, 0, len(c.interceptors)+len(intercetorsFromRequest)) 71 if len(intercetorsFromRequest) == 0 { 72 newInterceptorList = append(newInterceptorList, c.interceptors...) 73 } else if len(c.interceptors) == 0 { 74 newInterceptorList = intercetorsFromRequest 75 } else { 76 newInterceptorList = append(newInterceptorList, c.interceptors...) 77 newInterceptorList = append(newInterceptorList, intercetorsFromRequest...) 78 sort.Sort(newInterceptorList) 79 } 80 return newInterceptorList 81 } 82 83 func (c *client) Do(req *http.Request) (*http.Response, error) { 84 handler := func(req *http.Request) (*http.Response, error) { 85 return c.coreClient.Do(req) 86 } 87 newInterceptorList := c.mergeInterceptors(req) 88 for _, interceptor := range newInterceptorList { 89 h := handler 90 i := interceptor 91 handler = func(r *http.Request) (*http.Response, error) { 92 return i.Intercept(r, h) 93 } 94 } 95 96 return handleResponseAndError(handler(req)) 97 } 98 99 func Do(c Client, options RequestParams) (*http.Response, error) { 100 req, err := NewRequest(options) 101 if err != nil { 102 return nil, err 103 } 104 105 return handleResponseAndError(c.Do(req)) 106 } 107 108 func handleResponseAndError(resp *http.Response, err error) (*http.Response, error) { 109 if err != nil { 110 return resp, err 111 } 112 113 if resp == nil { 114 return nil, &clientV1.ErrorInfo{ 115 Code: -999, 116 Err: "unknown error, no response", 117 } 118 } 119 120 if resp.StatusCode/100 != 2 { 121 return resp, clientV1.ResponseError(resp) 122 } 123 124 return resp, nil 125 } 126 127 func DoAndDecodeJsonResponse(c Client, options RequestParams, ret interface{}) error { 128 resp, err := Do(c, options) 129 defer func() { 130 if resp != nil && resp.Body != nil { 131 _ = internal_io.SinkAll(resp.Body) 132 resp.Body.Close() 133 } 134 }() 135 136 if err != nil { 137 return err 138 } 139 140 if ret == nil || resp.ContentLength == 0 { 141 return nil 142 } 143 144 if err = clientV1.DecodeJsonFromReader(resp.Body, ret); err != nil { 145 return err 146 } 147 148 return nil 149 } 150 151 type clientV1Wrapper struct { 152 c *clientV1.Client 153 } 154 155 func (c *clientV1Wrapper) Do(req *http.Request) (*http.Response, error) { 156 return c.c.Do(req.Context(), req) 157 } 158 159 func NewClientWithClientV1(c *clientV1.Client) Client { 160 if c == nil { 161 c = &clientV1.DefaultClient 162 } 163 return &clientV1Wrapper{ 164 c: c, 165 } 166 }