github.com/frankrap/okex-api@v1.0.4/client.go (about) 1 package okex 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "net/url" 10 "strconv" 11 "strings" 12 "time" 13 ) 14 15 /* 16 http client, request, response 17 @author Tony Tian 18 @date 2018-03-17 19 @version 1.0.0 20 */ 21 22 type Client struct { 23 Config Config 24 HttpClient *http.Client 25 } 26 27 type ApiMessage struct { 28 Code int `json:"code"` 29 Message string `json:"message"` 30 } 31 32 /* 33 Get a http client 34 */ 35 func NewClient(config Config) *Client { 36 var client Client 37 client.Config = config 38 httpClient := config.HTTPClient 39 if httpClient == nil { 40 timeout := config.TimeoutSecond 41 if timeout <= 0 { 42 timeout = 30 43 } 44 transport := &http.Transport{} 45 if config.ProxyURL != "" { 46 proxyURL_, err := url.Parse(config.ProxyURL) 47 if err != nil { 48 return nil 49 } 50 transport.Proxy = http.ProxyURL(proxyURL_) 51 } 52 httpClient = &http.Client{ 53 Transport: transport, 54 Timeout: time.Duration(timeout) * time.Second, 55 } 56 } 57 client.HttpClient = httpClient 58 return &client 59 } 60 61 /* 62 Send a http request to remote server and get a response data 63 */ 64 func (client *Client) Request(method string, requestPath string, 65 params, result interface{}) (respBody []byte, response *http.Response, err error) { 66 config := client.Config 67 // uri 68 endpoint := config.Endpoint 69 if strings.HasSuffix(config.Endpoint, "/") { 70 endpoint = config.Endpoint[0 : len(config.Endpoint)-1] 71 } 72 url := endpoint + requestPath 73 74 // get json and bin styles request body 75 var jsonBody string 76 var binBody = bytes.NewReader(make([]byte, 0)) 77 if params != nil { 78 jsonBody, binBody, err = ParseRequestParams(params) 79 if err != nil { 80 return respBody, response, err 81 } 82 } 83 84 // get a http request 85 request, err := http.NewRequest(method, url, binBody) 86 if err != nil { 87 return respBody, response, err 88 } 89 90 // Sign and set request headers 91 timestamp := IsoTime() 92 preHash := PreHashString(timestamp, method, requestPath, jsonBody) 93 sign, err := HmacSha256Base64Signer(preHash, config.SecretKey) 94 if err != nil { 95 return respBody, response, err 96 } 97 Headers(request, config, timestamp, sign) 98 99 if config.IsPrint { 100 printRequest(config, request, jsonBody, preHash) 101 } 102 103 // send a request to remote server, and get a response 104 response, err = client.HttpClient.Do(request) 105 if err != nil { 106 return respBody, response, err 107 } 108 defer response.Body.Close() 109 110 // get a response results and parse 111 status := response.StatusCode 112 message := response.Status 113 body, err := ioutil.ReadAll(response.Body) 114 if err != nil { 115 return respBody, response, err 116 } 117 118 respBody = body 119 120 if config.IsPrint { 121 printResponse(status, message, body) 122 } 123 124 responseBodyString := string(body) 125 126 response.Header.Add(ResultDataJsonString, responseBodyString) 127 128 limit := response.Header.Get("Ok-Limit") 129 if limit != "" { 130 var page PageResult 131 page.Limit = StringToInt(limit) 132 from := response.Header.Get("Ok-From") 133 if from != "" { 134 page.From = StringToInt(from) 135 } 136 to := response.Header.Get("Ok-To") 137 if to != "" { 138 page.To = StringToInt(to) 139 } 140 pageJsonString, err := Struct2JsonString(page) 141 if err != nil { 142 return respBody, response, err 143 } 144 response.Header.Add(ResultPageJsonString, pageJsonString) 145 } 146 147 if status >= 200 && status < 300 { 148 //fmt.Printf("Resp: %v", string(body)) 149 if body != nil && result != nil { 150 err := JsonBytes2Struct(body, result) 151 if err != nil { 152 return respBody, response, err 153 } 154 } 155 return respBody, response, nil 156 } else if status >= 400 || status <= 500 { 157 errMsg := "Http error(400~500) result: status=" + IntToString(status) + ", message=" + message + ", body=" + responseBodyString 158 fmt.Println(errMsg) 159 if body != nil { 160 err := errors.New(errMsg) 161 return respBody, response, err 162 } 163 } else { 164 fmt.Println("Http error result: status=" + IntToString(status) + ", message=" + message + ", body=" + responseBodyString) 165 return respBody, response, errors.New(message) 166 } 167 return respBody, response, nil 168 } 169 170 func printRequest(config Config, request *http.Request, body string, preHash string) { 171 if config.SecretKey != "" { 172 fmt.Println(" Secret-Key: " + config.SecretKey) 173 } 174 fmt.Println(" Request(" + IsoTime() + "):") 175 fmt.Println("\tUrl: " + request.URL.String()) 176 fmt.Println("\tMethod: " + strings.ToUpper(request.Method)) 177 if len(request.Header) > 0 { 178 fmt.Println("\tHeaders: ") 179 for k, v := range request.Header { 180 if strings.Contains(k, "Ok-") { 181 k = strings.ToUpper(k) 182 } 183 fmt.Println("\t\t" + k + ": " + v[0]) 184 } 185 } 186 fmt.Println("\tBody: " + body) 187 if preHash != "" { 188 fmt.Println(" PreHash: " + preHash) 189 } 190 } 191 192 func printResponse(status int, message string, body []byte) { 193 fmt.Println(" Response(" + IsoTime() + "):") 194 statusString := strconv.Itoa(status) 195 message = strings.Replace(message, statusString, "", -1) 196 message = strings.Trim(message, " ") 197 fmt.Println("\tStatus: " + statusString) 198 fmt.Println("\tMessage: " + message) 199 fmt.Println("\tBody: " + string(body)) 200 }