2018-06-29 22:53:14 +00:00
package itglue
import (
2018-07-23 00:51:25 +00:00
"bytes"
2018-06-29 22:53:14 +00:00
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
2018-07-22 08:24:52 +00:00
//TBD: Implement
type Links struct { }
2018-07-22 07:41:33 +00:00
type Metadata struct {
CurrentPage int ` json:"current-page" `
NextPage interface { } ` json:"next-page" `
PrevPage interface { } ` json:"prev-page" `
TotalPages int ` json:"total-pages" `
TotalCount int ` json:"total-count" `
Filters struct {
} ` json:"filters" `
2018-06-29 22:53:14 +00:00
}
//ITGAPI contains the ITG API URL for North America, as well as the API key.
//Think of it as an instance of the API client
type ITGAPI struct {
Site string //Full URL ITG API
APIKey string //API Key
}
2018-07-23 00:51:25 +00:00
type Request struct {
2018-07-23 02:06:08 +00:00
ITG * ITGAPI
RestAction 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
URLValues url . Values //Parameters sent to ITG for filtering by conditions that utilize strings
RawURLValues string //URL values must be a string. Raw URL values allow an int to be used, for instance in a filter
Page int
PageSize int
2018-07-23 00:51:25 +00:00
}
2018-07-23 01:35:10 +00:00
//NewITGAPI expects the API key to be passed to it
//Returns a pointer to an ITGAPI struct
func NewITGAPI ( apiKey string ) * ITGAPI {
return & ITGAPI { Site : "https://api.itglue.com" , APIKey : apiKey }
}
2018-07-23 00:51:25 +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
func ( itg * ITGAPI ) NewRequest ( restAction , method string , body [ ] byte ) * Request {
req := Request { ITG : itg , RestAction : restAction , Method : method , Body : body }
req . URLValues = url . Values { }
return & req
}
//Do is a method of the Request struct which uses the data contained within the Request instance to perform an HTTP request to ConnectWise
func ( req * Request ) Do ( ) error {
itgurl , err := req . ITG . BuildURL ( req . RestAction )
if err != nil {
return fmt . Errorf ( "could not build url %s: %s" , req . RestAction , err )
}
//If pagination parameters are not being specified, then don't include them in the URL - not all endpoints will accept page and pagesize, they will 400 - bad request
if req . Page == 0 || req . PageSize == 0 {
2018-07-23 02:06:08 +00:00
itgurl . RawQuery = fmt . Sprintf ( "%s%s" , req . URLValues . Encode ( ) , req . RawURLValues )
2018-07-23 00:51:25 +00:00
} else {
2018-07-23 02:06:08 +00:00
itgurl . RawQuery = fmt . Sprintf ( "%s%s&page[number]=%d&page[size]=%d" , req . URLValues . Encode ( ) , req . RawURLValues , req . Page , req . PageSize )
2018-07-23 00:51:25 +00:00
}
client := & http . Client { }
jsonBuffer := bytes . NewReader ( req . Body )
httpreq , err := http . NewRequest ( req . Method , itgurl . String ( ) , jsonBuffer )
if err != nil {
return fmt . Errorf ( "could not construct http request: %s" , err )
}
httpreq . Header . Set ( "Content-Type" , "application/vnd.api+json" )
httpreq . Header . Set ( "x-api-key" , req . ITG . APIKey )
httpreq . Header . Set ( "cache-control" , "no-cache" )
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 )
}
return nil
}
2018-07-22 07:41:33 +00:00
func getHTTPResponseBody ( resp * http . Response ) ( [ ] byte , error ) {
2018-06-29 22:53:14 +00:00
if resp . StatusCode != http . StatusOK {
2018-07-22 07:41:33 +00:00
return nil , fmt . Errorf ( "ITG returned HTTP status code %s\n%s" , resp . Status , resp . Body )
2018-06-29 22:53:14 +00:00
}
body , err := ioutil . ReadAll ( resp . Body )
2018-07-22 07:41:33 +00:00
if err != nil {
return nil , fmt . Errorf ( "could not read http response body: %s" , err )
}
2018-06-29 22:53:14 +00:00
2018-07-22 07:41:33 +00:00
return body , nil
2018-06-29 22:53:14 +00:00
}
//BuildURL expects a restaction to be passed to it
//Returns the full request URL containing the ITG API domain prepended to the rest action
2018-07-22 07:41:33 +00:00
func ( itg * ITGAPI ) BuildURL ( restAction string ) ( * url . URL , error ) {
2018-06-29 22:56:22 +00:00
var itgurl * url . URL
itgurl , err := url . Parse ( itg . Site )
2018-07-22 07:41:33 +00:00
if err != nil {
return nil , fmt . Errorf ( "could not parse url %s: %s" , itg . Site , err )
}
2018-06-29 22:56:22 +00:00
itgurl . Path += restAction
2018-07-22 07:41:33 +00:00
return itgurl , nil
2018-06-29 22:53:14 +00:00
}