traefik/vendor/github.com/exoscale/egoscale/request.go
2017-10-31 10:42:03 +01:00

134 lines
2.7 KiB
Go

package egoscale
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strings"
)
func csQuotePlus(s string) string {
return strings.Replace(s, "+", "%20", -1)
}
func csEncode(s string) string {
return csQuotePlus(url.QueryEscape(s))
}
func rawValue(b json.RawMessage) (json.RawMessage, error) {
var m map[string]json.RawMessage
if err := json.Unmarshal(b, &m); err != nil {
return nil, err
}
for _, v := range m {
return v, nil
}
return nil, nil
}
func rawValues(b json.RawMessage) (json.RawMessage, error) {
var i []json.RawMessage
if err := json.Unmarshal(b, &i); err != nil {
return nil, nil
}
return i[0], nil
}
func (exo *Client) ParseResponse(resp *http.Response) (json.RawMessage, error) {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
a, err := rawValues(b)
if a == nil {
b, err = rawValue(b)
if err != nil {
return nil, err
}
}
if resp.StatusCode >= 400 {
var e Error
if err := json.Unmarshal(b, &e); err != nil {
return nil, err
}
/* Need to account for differet error types */
if e.ErrorCode != 0 {
return nil, e.Error()
} else {
var de DNSError
if err := json.Unmarshal(b, &de); err != nil {
return nil, err
}
return nil, fmt.Errorf("Exoscale error (%d): %s", resp.StatusCode, strings.Join(de.Name, "\n"))
}
}
return b, nil
}
func (exo *Client) Request(command string, params url.Values) (json.RawMessage, error) {
mac := hmac.New(sha1.New, []byte(exo.apiSecret))
keys := make([]string, 0)
unencoded := make([]string, 0)
params.Set("apikey", exo.apiKey)
params.Set("command", command)
params.Set("response", "json")
for k, _ := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
arg := k + "=" + csEncode(params[k][0])
unencoded = append(unencoded, arg)
}
sign_string := strings.ToLower(strings.Join(unencoded, "&"))
mac.Write([]byte(sign_string))
signature := csEncode(base64.StdEncoding.EncodeToString(mac.Sum(nil)))
query := params.Encode()
url := exo.endpoint + "?" + csQuotePlus(query) + "&signature=" + signature
resp, err := exo.client.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return exo.ParseResponse(resp)
}
func (exo *Client) DetailedRequest(uri string, params string, method string, header http.Header) (json.RawMessage, error) {
url := exo.endpoint + uri
req, err := http.NewRequest(method, url, strings.NewReader(params))
if err != nil {
return nil, err
}
req.Header = header
response, err := exo.client.Do(req)
if err != nil {
return nil, err
}
defer response.Body.Close()
return exo.ParseResponse(response)
}