-
Notifications
You must be signed in to change notification settings - Fork 11
/
http.go
156 lines (142 loc) · 3.96 KB
/
http.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
package dbhub
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"strings"
)
// sendRequestJSON sends a request to DBHub.io, formatting the returned result as JSON
func sendRequestJSON(queryUrl string, verifyServerCert bool, data url.Values, returnStructure interface{}) (err error) {
// Send the request
var body io.ReadCloser
body, err = sendRequest(queryUrl, verifyServerCert, data)
if body != nil {
defer body.Close()
}
if err != nil {
if body != nil {
// If there's useful error info in the returned JSON, return that as the error message
var z JSONError
err = json.NewDecoder(body).Decode(&z)
if err != nil {
return
}
err = fmt.Errorf("%s", z.Msg)
}
return
}
// Unmarshall the JSON response into the structure provided by the caller
if returnStructure != nil {
err = json.NewDecoder(body).Decode(returnStructure)
if err != nil {
return
}
}
return
}
// sendRequest sends a request to DBHub.io. It exists because http.PostForm() doesn't seem to have a way of changing
// header values.
func sendRequest(queryUrl string, verifyServerCert bool, data url.Values) (body io.ReadCloser, err error) {
// Disable verification of the server https cert, if we've been told to
var client http.Client
if !verifyServerCert {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client = http.Client{Transport: tr}
}
var req *http.Request
var resp *http.Response
req, err = http.NewRequest(http.MethodPost, queryUrl, strings.NewReader(data.Encode()))
if err != nil {
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("User-Agent", fmt.Sprintf("go-dbhub v%s", version))
resp, err = client.Do(req)
if err != nil {
return
}
// Return the response body, even if an error occurred. This lets us return useful error information provided as
// JSON in the body of the message
body = resp.Body
// Basic error handling, based on the status code received from the server
if resp.StatusCode != 200 {
// The returned status code indicates something went wrong
err = fmt.Errorf(resp.Status)
return
}
return
}
// sendUpload uploads a database to DBHub.io. It exists because the DBHub.io upload end point requires multi-part data
func sendUpload(queryUrl string, verifyServerCert bool, data *url.Values, dbBytes *[]byte) (body io.ReadCloser, err error) {
// Prepare the database file byte stream
var buf bytes.Buffer
w := multipart.NewWriter(&buf)
dbName := data.Get("dbname")
var wri io.Writer
if dbName != "" {
wri, err = w.CreateFormFile("file", dbName)
} else {
wri, err = w.CreateFormFile("file", "database.db")
}
if err != nil {
return
}
_, err = wri.Write(*dbBytes)
if err != nil {
return
}
// Add the headers
for i, j := range *data {
wri, err = w.CreateFormField(i)
if err != nil {
return
}
_, err = wri.Write([]byte(j[0]))
if err != nil {
return
}
}
err = w.Close()
if err != nil {
return
}
// Disable verification of the server https cert, if we've been told to
var client http.Client
if !verifyServerCert {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client = http.Client{Transport: tr}
}
// Prepare the request
var req *http.Request
var resp *http.Response
req, err = http.NewRequest(http.MethodPost, queryUrl, &buf)
if err != nil {
return
}
req.Header.Set("User-Agent", fmt.Sprintf("go-dbhub v%s", version))
req.Header.Set("Content-Type", w.FormDataContentType())
// Upload the database
resp, err = client.Do(req)
if err != nil {
return
}
// Return the response body, even if an error occurred. This lets us return useful error information provided as
// JSON in the body of the message
body = resp.Body
// Basic error handling, based on the status code received from the server
if resp.StatusCode != 201 {
// The returned status code indicates something went wrong
err = fmt.Errorf(resp.Status)
return
}
return
}