-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresp.go
154 lines (129 loc) · 3.4 KB
/
resp.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package greq
import (
"bytes"
"net/http"
"strings"
"github.com/gookit/goutil/fsutil"
"github.com/gookit/goutil/netutil/httpctype"
"github.com/gookit/goutil/netutil/httpreq"
)
// Response is a http.Response wrapper
type Response struct {
*http.Response
// decoder for response, default will extends from Client.respDecoder
decoder RespDecoder
}
// IsOK check response status code is 200
func (r *Response) IsOK() bool {
return httpreq.IsOK(r.StatusCode)
}
// IsSuccessful check response status code is in 200 - 300
func (r *Response) IsSuccessful() bool {
return httpreq.IsSuccessful(r.StatusCode)
}
// IsFail check response status code != 200
func (r *Response) IsFail() bool {
return !httpreq.IsOK(r.StatusCode)
}
// IsEmptyBody check response body is empty
func (r *Response) IsEmptyBody() bool {
return r.ContentLength <= 0
}
// ContentType get response content type
func (r *Response) ContentType() string {
return r.Header.Get(httpctype.Key)
}
// IsContentType check response content type is equals the given.
//
// Usage:
//
// resp, err := greq.Post("some.host/path")
// ok := resp.IsContentType("application/xml")
func (r *Response) IsContentType(prefix string) bool {
val := r.Header.Get(httpctype.Key)
return val != "" && strings.HasPrefix(val, prefix)
}
// IsJSONType check response content type is JSON
func (r *Response) IsJSONType() bool {
return r.IsContentType(httpctype.MIMEJSON)
}
// Decode get the raw http.Response
func (r *Response) Decode(ptr any) error {
defer r.QuietCloseBody()
return r.decoder.Decode(r.Response, ptr)
}
// SetDecoder for response
func (r *Response) SetDecoder(decoder RespDecoder) {
r.decoder = decoder
}
// BodyBuffer read body to buffer.
//
// NOTICE: must close resp body.
func (r *Response) BodyBuffer() *bytes.Buffer {
buf := &bytes.Buffer{}
// prof: Allocate memory in advance
if r.ContentLength > bytes.MinRead {
buf.Grow(int(r.ContentLength) + 2)
}
// NOTICE: must close resp body.
defer r.QuietCloseBody()
_, err := buf.ReadFrom(r.Body)
if err != nil {
panic(err)
}
return buf
}
// HeaderString convert response headers to string
func (r *Response) HeaderString() string {
buf := &bytes.Buffer{}
for key, values := range r.Header {
buf.WriteString(key)
buf.WriteString(": ")
buf.WriteString(strings.Join(values, ";"))
buf.WriteByte('\n')
}
return buf.String()
}
// BodyString convert response body to string
func (r *Response) BodyString() string {
return r.BodyBuffer().String()
}
// SaveFile file on the response body is not-nil.
func (r *Response) SaveFile(file string) (err error) {
if r.Body != nil {
defer r.QuietCloseBody()
err = fsutil.WriteFile(file, r.Body, fsutil.DefaultFilePerm)
}
return
}
// String convert Response to string
func (r *Response) String() string {
buf := &bytes.Buffer{}
buf.WriteString(r.Proto)
buf.WriteByte(' ')
buf.WriteString(r.Status)
buf.WriteByte('\n')
for key, values := range r.Header {
buf.WriteString(key)
buf.WriteString(": ")
buf.WriteString(strings.Join(values, ";"))
buf.WriteByte('\n')
}
if !r.IsEmptyBody() {
buf.WriteByte('\n')
_, _ = buf.ReadFrom(r.Body)
}
return buf.String()
}
// Result get the raw http.Response
func (r *Response) Result() *http.Response {
return r.Response
}
// CloseBody close resp body
func (r *Response) CloseBody() error {
return r.Body.Close()
}
// QuietCloseBody close resp body, ignore error
func (r *Response) QuietCloseBody() {
_ = r.Body.Close()
}