terraform/vendor/github.com/maximilien/softlayer-go/client/http_client.go

215 lines
4.7 KiB
Go

package client
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/http/httputil"
"os"
"path/filepath"
"regexp"
"text/template"
)
const NON_VERBOSE = "NON_VERBOSE"
type HttpClient struct {
HTTPClient *http.Client
username string
password string
useHttps bool
apiUrl string
nonVerbose bool
templatePath string
}
func NewHttpsClient(username, password, apiUrl, templatePath string) *HttpClient {
return NewHttpClient(username, password, apiUrl, templatePath, true)
}
func NewHttpClient(username, password, apiUrl, templatePath string, useHttps bool) *HttpClient {
pwd, err := os.Getwd()
if err != nil {
panic(err)
}
hClient := &HttpClient{
username: username,
password: password,
useHttps: useHttps,
apiUrl: apiUrl,
templatePath: filepath.Join(pwd, templatePath),
HTTPClient: http.DefaultClient,
nonVerbose: checkNonVerbose(),
}
return hClient
}
// Public methods
func (slc *HttpClient) DoRawHttpRequestWithObjectMask(path string, masks []string, requestType string, requestBody *bytes.Buffer) ([]byte, int, error) {
url := fmt.Sprintf("%s://%s:%s@%s/%s", slc.scheme(), slc.username, slc.password, slc.apiUrl, path)
url += "?objectMask="
for i := 0; i < len(masks); i++ {
url += masks[i]
if i != len(masks)-1 {
url += ";"
}
}
return slc.makeHttpRequest(url, requestType, requestBody)
}
func (slc *HttpClient) DoRawHttpRequestWithObjectFilter(path string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, int, error) {
url := fmt.Sprintf("%s://%s:%s@%s/%s", slc.scheme(), slc.username, slc.password, slc.apiUrl, path)
url += "?objectFilter=" + filters
return slc.makeHttpRequest(url, requestType, requestBody)
}
func (slc *HttpClient) DoRawHttpRequestWithObjectFilterAndObjectMask(path string, masks []string, filters string, requestType string, requestBody *bytes.Buffer) ([]byte, int, error) {
url := fmt.Sprintf("%s://%s:%s@%s/%s", slc.scheme(), slc.username, slc.password, slc.apiUrl, path)
url += "?objectFilter=" + filters
url += "&objectMask=filteredMask["
for i := 0; i < len(masks); i++ {
url += masks[i]
if i != len(masks)-1 {
url += ";"
}
}
url += "]"
return slc.makeHttpRequest(url, requestType, requestBody)
}
func (slc *HttpClient) DoRawHttpRequest(path string, requestType string, requestBody *bytes.Buffer) ([]byte, int, error) {
url := fmt.Sprintf("%s://%s:%s@%s/%s", slc.scheme(), slc.username, slc.password, slc.apiUrl, path)
return slc.makeHttpRequest(url, requestType, requestBody)
}
func (slc *HttpClient) GenerateRequestBody(templateData interface{}) (*bytes.Buffer, error) {
cwd, err := os.Getwd()
if err != nil {
return nil, err
}
bodyTemplate := template.Must(template.ParseFiles(filepath.Join(cwd, slc.templatePath)))
body := new(bytes.Buffer)
bodyTemplate.Execute(body, templateData)
return body, nil
}
func (slc *HttpClient) HasErrors(body map[string]interface{}) error {
if errString, ok := body["error"]; !ok {
return nil
} else {
return errors.New(errString.(string))
}
}
func (slc *HttpClient) CheckForHttpResponseErrors(data []byte) error {
var decodedResponse map[string]interface{}
err := json.Unmarshal(data, &decodedResponse)
if err != nil {
return err
}
if err := slc.HasErrors(decodedResponse); err != nil {
return err
}
return nil
}
// Private methods
func (slc *HttpClient) scheme() string {
if !slc.useHttps {
return "http"
}
return "https"
}
func (slc *HttpClient) makeHttpRequest(url string, requestType string, requestBody *bytes.Buffer) ([]byte, int, error) {
req, err := http.NewRequest(requestType, url, requestBody)
if err != nil {
return nil, 0, err
}
bs, err := httputil.DumpRequest(req, true)
if err != nil {
return nil, 0, err
}
if !slc.nonVerbose {
fmt.Fprintf(os.Stderr, "\n---\n[softlayer-go] Request:\n%s\n", hideCredentials(string(bs)))
}
resp, err := slc.HTTPClient.Do(req)
if err != nil {
return nil, 520, err
}
defer resp.Body.Close()
bs, err = httputil.DumpResponse(resp, true)
if err != nil {
return nil, resp.StatusCode, err
}
if !slc.nonVerbose {
fmt.Fprintf(os.Stderr, "[softlayer-go] Response:\n%s\n", hideCredentials(string(bs)))
}
responseBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, resp.StatusCode, err
}
return responseBody, resp.StatusCode, nil
}
// Private functions
func hideCredentials(s string) string {
hiddenStr := "\"password\":\"******\""
r := regexp.MustCompile(`"password":"[^"]*"`)
return r.ReplaceAllString(s, hiddenStr)
}
func checkNonVerbose() bool {
slGoNonVerbose := os.Getenv(NON_VERBOSE)
switch slGoNonVerbose {
case "yes":
return true
case "YES":
return true
case "true":
return true
case "TRUE":
return true
}
return false
}