-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathresponse.go
185 lines (154 loc) · 4.06 KB
/
response.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package httpreq
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"mime"
"net/http"
"os"
"path"
)
// Response is the main struct which holds the http.Response and data.
type Response struct {
resp *http.Response
data []byte
}
// Response returns the original http.Response
func (r *Response) Response() *http.Response {
return r.resp
}
// StatusCode returns the status code of the response
func (r *Response) StatusCode() int {
if r == nil || r.resp == nil {
return 0
}
return r.resp.StatusCode
}
// Headers returns the headers of the response
func (r *Response) Headers() http.Header {
if r == nil || r.resp == nil {
return nil
}
return r.resp.Header
}
// Body returns the response body
func (r *Response) Body() ([]byte, error) {
body, err := r.readBody()
if err != nil {
logger.Errorf("Can not read http.Response body Error: %v", err)
return nil, err
}
return body, nil
}
// DownloadFile looks for Content-Disposition header to find the filename attribute and returns the content-type
// header with saved file path that is saved under given downloadDir.
func (r *Response) DownloadFile(downloadDir string) (contentType string, filePath string, err error) {
headers := r.Headers()
if headers == nil {
err = errors.New("http response headers missing")
logger.Errorf("%v", err)
return "", "", err
}
contentType = headers.Get("Content-Type")
disposition := headers.Get("Content-Disposition")
if disposition == "" {
err = errors.New("content-disposition header missing")
logger.Errorf("%v", err)
return contentType, "", err
}
_, params, err := mime.ParseMediaType(disposition)
if err != nil {
logger.Errorf("mime.ParseMediaType error: %v", err)
return contentType, "", err
}
fileName := params["filename"]
if fileName == "" {
err = errors.New("filename missing in content-disposition")
logger.Errorf("%v", err)
return contentType, "", err
}
filePath = path.Join(downloadDir, fileName)
err = r.SaveFile(filePath)
if err != nil {
logger.Errorf("cannot save file error: %v", err)
return contentType, "", err
}
return contentType, filePath, nil
}
// SaveFile reads body and then saves the file defined in body
func (r *Response) SaveFile(filePath string) error {
data, err := r.readBody()
if err != nil {
logger.Errorf("Can not save response to file %s Error: %v", filePath, err)
return err
}
if len(data) == 0 {
err := errors.New("Downloaded file is empty. Can not save empty response to file " + filePath)
return err
}
f, err := os.Create(filePath)
if err != nil {
logger.Errorf("Can not create file %s Error: %v", filePath, err)
return err
}
defer f.Close()
_, err = io.Copy(f, bytes.NewReader(data))
if err != nil {
logger.Errorf("Can write to file %s Error: %v", filePath, err)
return err
}
err = f.Sync()
if err != nil {
logger.Errorf("Can't sync file %s Error: %v", filePath, err)
return err
}
return err
}
// Close closes the http.Response
func (r *Response) Close() error {
if r == nil || r.resp == nil || r.resp.Body == nil {
return nil
}
err := r.resp.Body.Close()
if err != nil {
logger.Errorf("Can't close http response body Error: %v", err)
return err
}
return nil
}
// readBody reads the http.Response body and assigns it to the r.Body
func (r *Response) readBody() ([]byte, error) {
// If r.data already set then return r.data
if len(r.data) != 0 {
return r.data, nil
}
// Check if Response.resp (*http.Response) is nil
if r.resp == nil {
err := fmt.Errorf("http.Response is nil")
logger.Errorf("%v", err)
return nil, err
}
// Check if Response.resp.Body (*http.Response.Body) is nil
if r.resp.Body == nil {
err := fmt.Errorf("http.Response's Body is nil")
logger.Errorf("%v", err)
return nil, err
}
// Read response body
b, err := ioutil.ReadAll(r.resp.Body)
if err != nil {
logger.Errorf("Can't read http.Response body Error: %v", err)
return nil, err
}
// Set response readBody
r.data = b
// Close response body
err = r.resp.Body.Close()
if err != nil {
logger.Errorf("Can't close http.Response body Error: %v", err)
return nil, err
}
return b, nil
}