//Package rest provides a RocketChat rest client. package rest import ( "bytes" "encoding/json" "errors" "fmt" "io" "io/ioutil" "log" "net/http" "net/url" ) var ( ResponseErr = fmt.Errorf("got false response") ) type Response interface { OK() error } type Client struct { Protocol string Host string Path string Port string Version string // Use this switch to see all network communication. Debug bool auth *authInfo } type Status struct { Success bool `json:"success"` Error string `json:"error"` Status string `json:"status"` Message string `json:"message"` } type authInfo struct { token string id string } func (s Status) OK() error { if s.Success { return nil } if len(s.Error) > 0 { return fmt.Errorf(s.Error) } if s.Status == "success" { return nil } if len(s.Message) > 0 { return fmt.Errorf("status: %s, message: %s", s.Status, s.Message) } return ResponseErr } // StatusResponse The base for the most of the json responses type StatusResponse struct { Status Channel string `json:"channel"` } func NewClient(serverUrl *url.URL, debug bool) *Client { protocol := "http" port := "80" if serverUrl.Scheme == "https" { protocol = "https" port = "443" } if len(serverUrl.Port()) > 0 { port = serverUrl.Port() } return &Client{Host: serverUrl.Hostname(), Path: serverUrl.Path, Port: port, Protocol: protocol, Version: "v1", Debug: debug} } func (c *Client) getUrl() string { if len(c.Version) == 0 { c.Version = "v1" } return fmt.Sprintf("%v://%v:%v%s/api/%s", c.Protocol, c.Host, c.Port, c.Path, c.Version) } // Get call Get func (c *Client) Get(api string, params url.Values, response Response) error { return c.doRequest(http.MethodGet, api, params, nil, response) } // Post call as JSON func (c *Client) Post(api string, body io.Reader, response Response) error { return c.doRequest(http.MethodPost, api, nil, body, response) } // PostForm call as Form Data func (c *Client) PostForm(api string, params url.Values, response Response) error { return c.doRequest(http.MethodPost, api, params, nil, response) } func (c *Client) doRequest(method, api string, params url.Values, body io.Reader, response Response) error { contentType := "application/x-www-form-urlencoded" if method == http.MethodPost { if body != nil { contentType = "application/json" } else if len(params) > 0 { body = bytes.NewBufferString(params.Encode()) } } request, err := http.NewRequest(method, c.getUrl()+"/"+api, body) if err != nil { return err } if method == http.MethodGet { if len(params) > 0 { request.URL.RawQuery = params.Encode() } } else { request.Header.Set("Content-Type", contentType) } if c.auth != nil { request.Header.Set("X-Auth-Token", c.auth.token) request.Header.Set("X-User-Id", c.auth.id) } if c.Debug { log.Println(request) } resp, err := http.DefaultClient.Do(request) if err != nil { return err } defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body) if c.Debug { log.Println(string(bodyBytes)) } var parse bool if err == nil { if e := json.Unmarshal(bodyBytes, response); e == nil { parse = true } } if resp.StatusCode != http.StatusOK { if parse { return response.OK() } return errors.New("Request error: " + resp.Status) } if err != nil { return err } return response.OK() }