2018-06-20 19:24:47 +00:00
|
|
|
package connectwise
|
|
|
|
|
|
|
|
import (
|
2018-07-07 00:26:11 +00:00
|
|
|
"bytes"
|
2018-06-20 19:24:47 +00:00
|
|
|
"fmt"
|
2018-06-20 21:59:12 +00:00
|
|
|
"io"
|
2018-06-20 19:24:47 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2018-06-20 20:23:49 +00:00
|
|
|
"net/url"
|
2018-06-20 19:24:47 +00:00
|
|
|
)
|
|
|
|
|
2018-07-06 22:21:00 +00:00
|
|
|
//Request is a struct which holds all information that is collected in order to make a request
|
|
|
|
type Request struct {
|
2018-07-07 00:29:53 +00:00
|
|
|
CW *Site
|
2018-07-06 22:21:00 +00:00
|
|
|
RestAction string
|
|
|
|
Parameters map[string]string
|
|
|
|
Method string //GET, POST, DELETE, etc
|
|
|
|
Body []byte //In a GET request, this is an instance of the struct that the expected json data is to be unmarshaled into
|
|
|
|
}
|
|
|
|
|
2018-07-07 00:26:11 +00:00
|
|
|
//NewRequest is a function which takes the mandatory fields to perform a request to the CW API and returns a pointer to a Request struct
|
2018-07-07 00:29:53 +00:00
|
|
|
func NewRequest(cw *Site, restAction, method string, body []byte) *Request {
|
2018-07-06 22:21:00 +00:00
|
|
|
req := Request{CW: cw, RestAction: restAction, Method: method, Body: body}
|
2018-07-07 22:31:45 +00:00
|
|
|
req.Parameters = make(map[string]string)
|
|
|
|
|
2018-07-06 22:21:00 +00:00
|
|
|
return &req
|
|
|
|
}
|
|
|
|
|
2018-07-07 00:26:11 +00:00
|
|
|
//Do is a method of the Request struct which uses the data contained within the Request instance to perform an HTTP request to ConnectWise
|
2018-07-06 22:21:00 +00:00
|
|
|
func (req *Request) Do() error {
|
|
|
|
cwurl, err := req.CW.BuildURL(req.RestAction)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not build url %s: %s", req.RestAction, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(req.Parameters) > 0 {
|
|
|
|
parameters := url.Values{}
|
|
|
|
for key, value := range req.Parameters {
|
|
|
|
parameters.Add(key, value)
|
|
|
|
}
|
|
|
|
cwurl.RawQuery = parameters.Encode()
|
|
|
|
}
|
|
|
|
|
2018-07-07 00:26:11 +00:00
|
|
|
client := &http.Client{}
|
|
|
|
jsonBuffer := bytes.NewReader(req.Body)
|
|
|
|
httpreq, err := http.NewRequest(req.Method, cwurl.String(), jsonBuffer)
|
2018-07-06 22:21:00 +00:00
|
|
|
if err != nil {
|
2018-07-07 00:26:11 +00:00
|
|
|
return fmt.Errorf("could not construct http request: %s", err)
|
|
|
|
}
|
|
|
|
httpreq.Header.Set("Authorization", req.CW.Auth)
|
|
|
|
httpreq.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := client.Do(httpreq)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("could not perform http %s request: %s", req.Method, err)
|
|
|
|
}
|
|
|
|
req.Body, err = getHTTPResponseBody(resp)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to get http response body: %s", err)
|
2018-07-06 22:21:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-06-29 01:35:34 +00:00
|
|
|
//BuildURL will take a REST action such as "/companies/company/5" and then append the CW site to it and return a pointer to a url.URL
|
2018-07-07 00:29:53 +00:00
|
|
|
func (cw *Site) BuildURL(restAction string) (*url.URL, error) {
|
2018-06-29 01:35:34 +00:00
|
|
|
var cwurl *url.URL
|
|
|
|
cwurl, err := url.Parse(cw.Site)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not %s as url: %s", cw.Site, err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-29 01:35:34 +00:00
|
|
|
cwurl.Path += restAction
|
2018-06-23 00:47:39 +00:00
|
|
|
|
2018-07-06 03:20:52 +00:00
|
|
|
return cwurl, nil
|
2018-06-23 00:47:39 +00:00
|
|
|
}
|
|
|
|
|
2018-06-20 19:24:47 +00:00
|
|
|
//Checks for HTTP errors, and if all looks good, returns the body of the HTTP response as a byte slice
|
2018-06-20 21:59:12 +00:00
|
|
|
//TBD: Needs to accept 201 and 204 (returned for Create and Delete operations)
|
2018-07-06 03:20:52 +00:00
|
|
|
func getHTTPResponseBody(resp *http.Response) ([]byte, error) {
|
2018-06-22 20:14:21 +00:00
|
|
|
if (resp.StatusCode != http.StatusOK) && (resp.StatusCode != http.StatusCreated) && (resp.StatusCode != http.StatusNoContent) {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("cw api returned unexpected http status %d - %s", resp.StatusCode, resp.Status)
|
2018-06-20 19:24:47 +00:00
|
|
|
}
|
2018-07-06 03:20:52 +00:00
|
|
|
defer resp.Body.Close()
|
2018-06-29 01:35:34 +00:00
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("could not read response body of request")
|
|
|
|
}
|
2018-06-29 01:35:34 +00:00
|
|
|
|
2018-07-06 03:20:52 +00:00
|
|
|
return body, nil
|
2018-06-20 19:24:47 +00:00
|
|
|
}
|
2018-06-20 20:23:49 +00:00
|
|
|
|
2018-07-07 00:29:53 +00:00
|
|
|
//GetRequest takes a Site and request URL, and returns the body of the response
|
|
|
|
func (cw *Site) GetRequest(cwurl *url.URL) ([]byte, error) {
|
2018-06-20 20:23:49 +00:00
|
|
|
client := &http.Client{}
|
2018-06-29 01:35:34 +00:00
|
|
|
req, err := http.NewRequest("GET", cwurl.String(), nil)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not construct http request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-23 03:14:08 +00:00
|
|
|
req.Header.Set("Authorization", cw.Auth)
|
2018-06-20 20:23:49 +00:00
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
response, err := client.Do(req)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not perform http get request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
body, err := getHTTPResponseBody(response)
|
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not get http response body: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-20 20:23:49 +00:00
|
|
|
|
2018-07-06 03:20:52 +00:00
|
|
|
return body, nil
|
2018-06-20 20:23:49 +00:00
|
|
|
}
|
2018-06-20 21:59:12 +00:00
|
|
|
|
2018-07-07 00:29:53 +00:00
|
|
|
//PostRequest takes a Site and request URL, and returns the body of the response
|
|
|
|
func (cw *Site) PostRequest(cwurl *url.URL, reqBody io.Reader) ([]byte, error) {
|
2018-06-20 21:59:12 +00:00
|
|
|
client := &http.Client{}
|
2018-07-06 03:20:52 +00:00
|
|
|
req, err := http.NewRequest("POST", cwurl.String(), reqBody)
|
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not construct http request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-23 03:14:08 +00:00
|
|
|
req.Header.Set("Authorization", cw.Auth)
|
2018-06-20 21:59:12 +00:00
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
response, err := client.Do(req)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not perform http post request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
body, err := getHTTPResponseBody(response)
|
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not get http response body: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-20 21:59:12 +00:00
|
|
|
|
2018-07-06 03:20:52 +00:00
|
|
|
return body, nil
|
2018-06-20 21:59:12 +00:00
|
|
|
}
|
|
|
|
|
2018-07-07 00:29:53 +00:00
|
|
|
//DeleteRequest takes a Site and request URL, and returns the body of the response
|
|
|
|
func (cw *Site) DeleteRequest(cwurl *url.URL) ([]byte, error) {
|
2018-06-20 21:59:12 +00:00
|
|
|
client := &http.Client{}
|
2018-06-29 01:35:34 +00:00
|
|
|
req, err := http.NewRequest("DELETE", cwurl.String(), nil)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not construct http request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-23 03:14:08 +00:00
|
|
|
req.Header.Set("Authorization", cw.Auth)
|
2018-06-20 21:59:12 +00:00
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
response, err := client.Do(req)
|
2018-07-06 03:20:52 +00:00
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not perform http delete request: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
body, err := getHTTPResponseBody(response)
|
|
|
|
if err != nil {
|
2018-07-06 14:37:53 +00:00
|
|
|
return nil, fmt.Errorf("could not get http response body: %s", err)
|
2018-07-06 03:20:52 +00:00
|
|
|
}
|
2018-06-20 21:59:12 +00:00
|
|
|
|
2018-07-06 03:20:52 +00:00
|
|
|
return body, nil
|
2018-06-20 21:59:12 +00:00
|
|
|
}
|