-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
121 lines (113 loc) · 3.18 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package util
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strconv"
)
// // Retry 重试
// // 当 fn() 返回错误不是 nil 时,按指定 interval 时间间隔后,重试 fn();
// // 若 fn() == nil, 则不进行重试
// // n 表示最大重试次数;若重试都失败,则返回最后一次的错误;若重试期间成功,则返回 nil
// func Retry(interval time.Duration, maxRetry int, fn func(n int) error) error {
// var err error
// for i := 1; i <= maxRetry; i++ {
// err = fn(i)
// if err == nil {
// return nil
// }
// time.Sleep(interval)
// }
//
// return err
// }
// DrainBody reads all of b to memory and then returns bytes of b and a ReadCloser
// yielding the same bytes.
//
// It returns an error if the initial slurp of all bytes fails. It does not attempt
// to make the returned ReadCloser have identical error-matching behavior.
func DrainBody(b io.ReadCloser) (rb []byte, nopb io.ReadCloser, err error) {
if b == http.NoBody {
// No copying needed. Preserve the magic sentinel meaning of NoBody.
return nil, http.NoBody, nil
}
var buf bytes.Buffer
if _, err = buf.ReadFrom(b); err != nil {
return nil, b, err
}
if err = b.Close(); err != nil {
return nil, b, err
}
return buf.Bytes(), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
}
// ResolveReferenceURL resolves a URI reference to an absolute URI from an absolute base URI u, per RFC 3986
// Section 5.2. The URI reference may be relative or absolute. ResolveReferenceURL always returns a new URL instance,
// even if the returned URL is identical to either the base or reference. If ref is an absolute URL, then
// ResolveReferenceURL ignores base and returns a copy of ref.
func ResolveReferenceURL(base, ref string) (*url.URL, error) {
bu, err := url.Parse(base)
if err != nil {
return bu, err
}
return bu.Parse(ref)
}
// ToString convert v to string
func ToString(v interface{}) string {
var s string
switch v.(type) {
case string:
s = v.(string)
case []byte:
s = string(v.([]byte))
case []rune:
s = string(v.([]rune))
case int:
s = strconv.Itoa(v.(int))
case int8:
s = strconv.Itoa(int(v.(int8)))
case int16:
s = strconv.Itoa(int(v.(int16)))
case int32: // as rune
s = strconv.FormatInt(int64(v.(int32)), 10)
case int64:
s = strconv.FormatInt(v.(int64), 10)
case uint:
s = strconv.FormatUint(uint64(v.(uint)), 10)
case uint8: // as byte
s = strconv.FormatUint(uint64(v.(uint8)), 10)
case uint16:
s = strconv.FormatUint(uint64(v.(uint16)), 10)
case uint32:
s = strconv.FormatUint(uint64(v.(uint32)), 10)
case uint64:
s = strconv.FormatUint(v.(uint64), 10)
case float32:
s = strconv.FormatFloat(float64(v.(float32)), 'f', -1, 64)
case float64:
s = strconv.FormatFloat(v.(float64), 'f', -1, 64)
case bool:
s = strconv.FormatBool(v.(bool))
default:
s = fmt.Sprint(v)
}
return s
}
func ResetBody(req *http.Request, b []byte) {
if len(b) == 0 {
req.ContentLength = 0
req.Body = nil
req.GetBody = nil
return
}
body := bytes.NewReader(b)
req.Body = ioutil.NopCloser(body)
req.ContentLength = int64(body.Len())
snapshot := *body
req.GetBody = func() (io.ReadCloser, error) {
r := snapshot
return ioutil.NopCloser(&r), nil
}
}