github.com/qiniu/go-sdk/v7@v7.27.0/sms/rpc/client.go (about) 1 package rpc 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "net/url" 10 "strings" 11 "time" 12 ) 13 14 var ( 15 green = string([]byte{27, 91, 57, 55, 59, 52, 50, 109}) 16 white = string([]byte{27, 91, 57, 48, 59, 52, 55, 109}) 17 yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109}) 18 red = string([]byte{27, 91, 57, 55, 59, 52, 49, 109}) 19 blue = string([]byte{27, 91, 57, 55, 59, 52, 52, 109}) 20 magenta = string([]byte{27, 91, 57, 55, 59, 52, 53, 109}) 21 cyan = string([]byte{27, 91, 57, 55, 59, 52, 54, 109}) 22 reset = string([]byte{27, 91, 48, 109}) 23 ) 24 25 // UserAgent user agent 26 var UserAgent = "Golang qiniu/rpc package" 27 28 // -------------------------------------------------------------------- 29 30 // Client a golang http client 31 type Client struct { 32 *http.Client 33 } 34 35 // DefaultClient a golang default http client 36 var DefaultClient = Client{&http.Client{Transport: DefaultTransport}} 37 38 // NewClientTimeout return a golang http client 39 func NewClientTimeout(dial, resp time.Duration) Client { 40 return Client{&http.Client{Transport: NewTransportTimeout(dial, resp)}} 41 } 42 43 // -------------------------------------------------------------------- 44 45 // Head send head method request 46 func (r Client) Head(url string) (resp *http.Response, err error) { 47 req, err := http.NewRequest("HEAD", url, nil) 48 if err != nil { 49 return 50 } 51 return r.Do(req) 52 } 53 54 // Get send get method request 55 func (r Client) Get(url string) (resp *http.Response, err error) { 56 req, err := http.NewRequest("GET", url, nil) 57 if err != nil { 58 return 59 } 60 return r.Do(req) 61 } 62 63 // Delete send delete method request 64 func (r Client) Delete(url string) (resp *http.Response, err error) { 65 req, err := http.NewRequest("DELETE", url, nil) 66 if err != nil { 67 return 68 } 69 return r.Do(req) 70 } 71 72 // PostEx send post method request with url 73 func (r Client) PostEx(url string) (resp *http.Response, err error) { 74 req, err := http.NewRequest("POST", url, nil) 75 if err != nil { 76 return 77 } 78 return r.Do(req) 79 } 80 81 // PostWith send post method request with url, bodyType, body and bodyLength 82 func (r Client) PostWith(url1 string, bodyType string, body io.Reader, bodyLength int) (resp *http.Response, err error) { 83 req, err := http.NewRequest("POST", url1, body) 84 if err != nil { 85 return 86 } 87 req.Header.Set("Content-Type", bodyType) 88 req.ContentLength = int64(bodyLength) 89 return r.Do(req) 90 } 91 92 // PostWith64 send post method request with url, bodyType, body and bodyLength(64) 93 func (r Client) PostWith64(url1 string, bodyType string, body io.Reader, bodyLength int64) (resp *http.Response, err error) { 94 req, err := http.NewRequest("POST", url1, body) 95 if err != nil { 96 return 97 } 98 req.Header.Set("Content-Type", bodyType) 99 req.ContentLength = bodyLength 100 return r.Do(req) 101 } 102 103 // PostWithForm send post method request with url and form data 104 func (r Client) PostWithForm(url1 string, data map[string][]string) (resp *http.Response, err error) { 105 msg := url.Values(data).Encode() 106 return r.PostWith(url1, "application/x-www-form-urlencoded", strings.NewReader(msg), len(msg)) 107 } 108 109 // PostWithJSON send post method request with url and application/json data 110 func (r Client) PostWithJSON(url1 string, data interface{}) (resp *http.Response, err error) { 111 msg, err := json.Marshal(data) 112 if err != nil { 113 return 114 } 115 return r.PostWith(url1, "application/json", bytes.NewReader(msg), len(msg)) 116 } 117 118 // PutEx send put request with url 119 func (r Client) PutEx(url string) (resp *http.Response, err error) { 120 req, err := http.NewRequest("PUT", url, nil) 121 if err != nil { 122 return 123 } 124 return r.Do(req) 125 } 126 127 // PutWith send put method request with url, bodyType, body and bodyLength 128 func (r Client) PutWith(url1 string, bodyType string, body io.Reader, bodyLength int) (resp *http.Response, err error) { 129 req, err := http.NewRequest("PUT", url1, body) 130 if err != nil { 131 return 132 } 133 req.Header.Set("Content-Type", bodyType) 134 req.ContentLength = int64(bodyLength) 135 return r.Do(req) 136 } 137 138 // PutWith64 send put method request with url, bodyType, body and bodyLength(64) 139 func (r Client) PutWith64(url1 string, bodyType string, body io.Reader, bodyLength int64) (resp *http.Response, err error) { 140 req, err := http.NewRequest("PUT", url1, body) 141 if err != nil { 142 return 143 } 144 req.Header.Set("Content-Type", bodyType) 145 req.ContentLength = bodyLength 146 return r.Do(req) 147 } 148 149 // PutWithForm send put method request with url and form data 150 func (r Client) PutWithForm(url1 string, data map[string][]string) (resp *http.Response, err error) { 151 msg := url.Values(data).Encode() 152 return r.PutWith(url1, "application/x-www-form-urlencoded", strings.NewReader(msg), len(msg)) 153 } 154 155 // PutWithJSON send put method request with url and application/json data 156 func (r Client) PutWithJSON(url1 string, data interface{}) (resp *http.Response, err error) { 157 msg, err := json.Marshal(data) 158 if err != nil { 159 return 160 } 161 return r.PutWith(url1, "application/json", bytes.NewReader(msg), len(msg)) 162 } 163 164 // -------------------------------------------------------------------- 165 166 // Do 发送 HTTP Request, 并返回 HTTP Response 167 func (r Client) Do(req *http.Request) (resp *http.Response, err error) { 168 // debug 169 start := time.Now() 170 defer func() { 171 end := time.Now() 172 latency := end.Sub(start) 173 if err != nil { 174 } else { 175 reqid := req.Header.Get("X-Reqid") 176 if rid := resp.Header.Get("X-Reqid"); len(rid) > 0 { 177 reqid = rid 178 } 179 method := req.Method 180 methodColor := colorForMethod(method) 181 statusCode := resp.StatusCode 182 statusColor := colorForStatus(statusCode) 183 184 fmt.Printf("[RPC] [%s] %v |%s %3d %s| %13v |%s %s %s|\t %s\n", 185 reqid, 186 start.Format("2006/01/02 - 15:04:05"), 187 statusColor, statusCode, reset, 188 latency, 189 methodColor, method, reset, 190 req.URL.String(), 191 ) 192 } 193 }() 194 195 if req.Header.Get("User-Agent") == "" { 196 req.Header.Set("User-Agent", UserAgent) 197 } 198 199 resp, err = r.Client.Do(req) 200 return 201 } 202 203 // -------------------------------------------------------------------- 204 205 // ErrorInfo type 206 type ErrorInfo struct { 207 Err string `json:"error"` 208 RequestID string `json:"reqid"` 209 Message string `json:"message"` 210 Code int `json:"code"` 211 } 212 213 // ErrorDetail return error detail 214 func (r *ErrorInfo) ErrorDetail() string { 215 msg, _ := json.Marshal(r) 216 return string(msg) 217 } 218 219 // Error return error message 220 func (r *ErrorInfo) Error() string { 221 if r.Err != "" { 222 return r.Err 223 } 224 return http.StatusText(r.Code) 225 } 226 227 // HTTPCode return rpc http StatusCode 228 func (r *ErrorInfo) HTTPCode() int { 229 return r.Code 230 } 231 232 // -------------------------------------------------------------------- 233 234 type errorRet struct { 235 Error string `json:"error"` 236 } 237 238 // ResponseError return response error 239 func ResponseError(resp *http.Response) (err error) { 240 e := &ErrorInfo{ 241 RequestID: resp.Header.Get("X-Reqid"), 242 Code: resp.StatusCode, 243 } 244 if resp.StatusCode > 299 { 245 if resp.ContentLength != 0 { 246 if ct := resp.Header.Get("Content-Type"); strings.TrimSpace(strings.SplitN(ct, ";", 2)[0]) == "application/json" { 247 var ret1 errorRet 248 json.NewDecoder(resp.Body).Decode(&ret1) 249 e.Err = ret1.Error 250 } 251 } 252 } 253 return e 254 } 255 256 // CallRet parse http response 257 func CallRet(ret interface{}, resp *http.Response) (err error) { 258 return callRet(ret, resp) 259 } 260 261 // callRet parse http response 262 func callRet(ret interface{}, resp *http.Response) (err error) { 263 defer func() { 264 io.Copy(io.Discard, resp.Body) 265 resp.Body.Close() 266 }() 267 268 if resp.StatusCode/100 == 2 || resp.StatusCode/100 == 3 { 269 if ret != nil && resp.ContentLength != 0 { 270 err = json.NewDecoder(resp.Body).Decode(ret) 271 if err != nil { 272 return 273 } 274 } 275 return nil 276 } 277 return ResponseError(resp) 278 } 279 280 // CallWithForm send post method request with url and form data then parse response 281 func (r Client) CallWithForm(ret interface{}, url1 string, param map[string][]string) (err error) { 282 resp, err := r.PostWithForm(url1, param) 283 if err != nil { 284 return err 285 } 286 return callRet(ret, resp) 287 } 288 289 // CallWithJSON send post method request with url and application/json data then parse response 290 func (r Client) CallWithJSON(ret interface{}, url1 string, param interface{}) (err error) { 291 resp, err := r.PostWithJSON(url1, param) 292 if err != nil { 293 return err 294 } 295 return callRet(ret, resp) 296 } 297 298 // CallWith send post method request with url, bodyType, body and bodyLength then parse response 299 func (r Client) CallWith(ret interface{}, url1 string, bodyType string, body io.Reader, bodyLength int) (err error) { 300 resp, err := r.PostWith(url1, bodyType, body, bodyLength) 301 if err != nil { 302 return err 303 } 304 return callRet(ret, resp) 305 } 306 307 // CallWith64 send post method request with url, bodyType, body and bodyLength(64) then parse response 308 func (r Client) CallWith64(ret interface{}, url1 string, bodyType string, body io.Reader, bodyLength int64) (err error) { 309 resp, err := r.PostWith64(url1, bodyType, body, bodyLength) 310 if err != nil { 311 return err 312 } 313 return callRet(ret, resp) 314 } 315 316 // Call send post method request with url then parse response 317 func (r Client) Call(ret interface{}, url1 string) (err error) { 318 resp, err := r.PostWith(url1, "application/x-www-form-urlencoded", nil, 0) 319 if err != nil { 320 return err 321 } 322 return callRet(ret, resp) 323 } 324 325 // PutCallWithForm send put method request with url and param then parse response 326 func (r Client) PutCallWithForm(ret interface{}, url1 string, param map[string][]string) (err error) { 327 resp, err := r.PutWithForm(url1, param) 328 if err != nil { 329 return err 330 } 331 return callRet(ret, resp) 332 } 333 334 // PutCallWithJSON send put method request with url and param then parse response 335 func (r Client) PutCallWithJSON(ret interface{}, url1 string, param interface{}) (err error) { 336 resp, err := r.PutWithJSON(url1, param) 337 if err != nil { 338 return err 339 } 340 return callRet(ret, resp) 341 } 342 343 // PutCallWith send put method request with url, bodyType, body and bodyLength then parse response 344 func (r Client) PutCallWith(ret interface{}, url1 string, bodyType string, body io.Reader, bodyLength int) (err error) { 345 resp, err := r.PutWith(url1, bodyType, body, bodyLength) 346 if err != nil { 347 return err 348 } 349 return callRet(ret, resp) 350 } 351 352 // PutCallWith64 send post method request with url, bodyType, body and bodyLength(64) then parse response 353 func (r Client) PutCallWith64(ret interface{}, url1 string, bodyType string, body io.Reader, bodyLength int64) (err error) { 354 resp, err := r.PutWith64(url1, bodyType, body, bodyLength) 355 if err != nil { 356 return err 357 } 358 return callRet(ret, resp) 359 } 360 361 // PutCall send put method request with url then parse response 362 func (r Client) PutCall(ret interface{}, url1 string) (err error) { 363 resp, err := r.PutWith(url1, "application/x-www-form-urlencoded", nil, 0) 364 if err != nil { 365 return err 366 } 367 return callRet(ret, resp) 368 } 369 370 // GetCall send get method request with url then parse response 371 func (r Client) GetCall(ret interface{}, url1 string) (err error) { 372 resp, err := r.Get(url1) 373 if err != nil { 374 return err 375 } 376 return callRet(ret, resp) 377 } 378 379 // GetCallWithForm send get method request with url and param then parse response 380 func (r Client) GetCallWithForm(ret interface{}, url1 string, param map[string][]string) (err error) { 381 payload := url.Values(param).Encode() 382 if strings.ContainsRune(url1, '?') { 383 url1 += "&" 384 } else { 385 url1 += "?" 386 } 387 url1 += payload 388 resp, err := r.Get(url1) 389 if err != nil { 390 return err 391 } 392 return callRet(ret, resp) 393 } 394 395 // DeleteCall send delete method request with url 396 func (r Client) DeleteCall(ret interface{}, url string) (err error) { 397 resp, err := r.Delete(url) 398 if err != nil { 399 return err 400 } 401 return callRet(ret, resp) 402 } 403 404 // -------------------------------------------------------------------- 405 406 func colorForStatus(code int) string { 407 switch { 408 case code >= 200 && code < 300: 409 return green 410 case code >= 300 && code < 400: 411 return white 412 case code >= 400 && code < 500: 413 return yellow 414 default: 415 return red 416 } 417 } 418 419 func colorForMethod(method string) string { 420 switch method { 421 case "GET": 422 return blue 423 case "POST": 424 return cyan 425 case "PUT": 426 return yellow 427 case "DELETE": 428 return red 429 case "PATCH": 430 return green 431 case "HEAD": 432 return magenta 433 case "OPTIONS": 434 return white 435 default: 436 return reset 437 } 438 }