123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- package grafana
-
- import (
- "bytes"
- "fmt"
- "io/ioutil"
- "net/http"
- "strings"
- )
-
- // Client implements a Grafana API client, and contains the instance's base URL
- // and API key, along with an HTTP client used to request the API.
- type Client struct {
- BaseURL string
- APIKey string
- httpClient *http.Client
- }
-
- // NewClient returns a new Grafana API client from a given base URL and API key.
- func NewClient(baseURL string, apiKey string) (c *Client) {
- // Grafana doesn't support double slashes in the API routes, so we strip the
- // last slash if there's one, because request() will append one anyway.
- if strings.HasSuffix(baseURL, "/") {
- baseURL = baseURL[:len(baseURL)-1]
- }
-
- return &Client{
- BaseURL: baseURL,
- APIKey: apiKey,
- httpClient: new(http.Client),
- }
- }
-
- // request preforms an HTTP request on a given endpoint, with a given method and
- // body. The endpoint is the Grafana API route to request, without the "/api/"
- // part. If the request doesn't require a body, the function has to be called
- // with "nil" as the "body" parameter.
- // Returns the response body (as a []byte containing JSON data).
- // Returns an error if there was an issue initialising the request, performing
- // it or reading the response body. Also returns an error on non-200 response
- // status codes. If the status code is 404, a standard error is returned, if the
- // status code is neither 200 nor 404 an error of type httpUnkownError is
- // returned.
- func (c *Client) request(method string, endpoint string, body []byte) ([]byte, error) {
- url := c.BaseURL + "/api/" + endpoint
-
- // Create the request
- req, err := http.NewRequest(method, url, bytes.NewBuffer(body))
- if err != nil {
- return nil, err
- }
-
- // Add the API key to the request as an Authorization HTTP header
- authHeader := fmt.Sprintf("Bearer %s", c.APIKey)
- req.Header.Add("Authorization", authHeader)
-
- // If the request isn't a GET, the body will be sent as JSON, so we need to
- // append the appropriate header
- if method != "GET" {
- req.Header.Add("Content-Type", "application/json")
- }
-
- // Perform the request
- resp, err := c.httpClient.Do(req)
- if err != nil {
- return nil, err
- }
-
- // Read the response body
- respBody, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- // Return an error if the Grafana API responded with a non-200 status code.
- // We perform this here because http.Client.Do() doesn't return with an
- // error on non-200 status codes.
- if resp.StatusCode != http.StatusOK {
- if resp.StatusCode == http.StatusNotFound {
- err = fmt.Errorf("%s not found (404)", url)
- } else {
- // Return an httpUnkownError error if the status code is neither 200
- // nor 404
- err = newHttpUnknownError(resp.StatusCode)
- }
- }
-
- // Return the response body along with the error. This allows callers to
- // process httpUnkownError errors by displaying an error message located in
- // the response body along with the data contained in the error.
- return respBody, err
- }
-
- // httpUnkownError represents an HTTP error, created from an HTTP response where
- // the status code is neither 200 nor 404.
- type httpUnkownError struct {
- StatusCode int
- }
-
- // newHttpUnknownError creates and returns a new httpUnkownError error using
- // the provided status code.
- func newHttpUnknownError(statusCode int) *httpUnkownError {
- return &httpUnkownError{
- StatusCode: statusCode,
- }
- }
-
- // Error implements error.Error().
- func (e *httpUnkownError) Error() string {
- return fmt.Sprintf("Unknown HTTP error: %d", e.StatusCode)
- }
|