api.go
author Mikael Berthe <mikael@lilotux.net>
Sat, 15 Apr 2017 21:08:34 +0200
changeset 125 2bbb72b9ebf6
child 128 a5a00fad7a32
permissions -rw-r--r--
Rework the API wrappers to handle arrays of parameters This make some API calls work better (reports with several statuses, statuses with several attachments, relationships for multiple accounts...).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
125
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     1
package gondole
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     2
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     3
import (
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     4
	"bytes"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     5
	"encoding/json"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     6
	"fmt"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     7
	"net/http"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     8
	"net/url"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
     9
	"strings"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    10
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    11
	"github.com/sendgrid/rest"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    12
)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    13
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    14
// restAPI actually does the HTTP query
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    15
// It is a copy of rest.API with better handling of parameters with multiple values
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    16
func restAPI(request rest.Request) (*rest.Response, error) {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    17
	c := &rest.Client{HTTPClient: http.DefaultClient}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    18
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    19
	// Build the HTTP request object.
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    20
	if len(request.QueryParams) != 0 {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    21
		// Add parameters to the URL
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    22
		request.BaseURL += "?"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    23
		urlp := url.Values{}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    24
		for key, value := range request.QueryParams {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    25
			// It seems Mastodon doesn't like parameters with index
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    26
			// numbers, but it needs the brackets.
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    27
			// Let's check if the key matches '^.+\[.*\]$'
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    28
			klen := len(key)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    29
			if klen == 0 {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    30
				continue
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    31
			}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    32
			i := strings.Index(key, "[")
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    33
			if key[klen-1] == ']' && i > 0 {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    34
				// This is an array, let's remove the index number
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    35
				key = key[:i] + "[]"
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    36
			}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    37
			urlp.Add(key, value)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    38
		}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    39
		urlpstr := urlp.Encode()
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    40
		request.BaseURL += urlpstr
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    41
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    42
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    43
	req, err := http.NewRequest(string(request.Method), request.BaseURL, bytes.NewBuffer(request.Body))
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    44
	if err != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    45
		return nil, err
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    46
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    47
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    48
	for key, value := range request.Headers {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    49
		req.Header.Set(key, value)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    50
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    51
	_, exists := req.Header["Content-Type"]
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    52
	if len(request.Body) > 0 && !exists {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    53
		req.Header.Set("Content-Type", "application/json")
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    54
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    55
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    56
	// Build the HTTP client and make the request.
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    57
	res, err := c.MakeRequest(req)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    58
	if err != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    59
		return nil, err
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    60
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    61
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    62
	// Build Response object.
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    63
	response, err := rest.BuildResponse(res)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    64
	if err != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    65
		return nil, err
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    66
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    67
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    68
	return response, nil
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    69
}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    70
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    71
// prepareRequest inserts all pre-defined stuff
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    72
func (g *Client) prepareRequest(target string, method rest.Method, params apiCallParams) (req rest.Request) {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    73
	endPoint := g.APIBase + "/" + target
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    74
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    75
	// Request headers
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    76
	hdrs := make(map[string]string)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    77
	hdrs["User-Agent"] = fmt.Sprintf("Gondole/%s", GondoleVersion)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    78
	if g.UserToken != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    79
		hdrs["Authorization"] = fmt.Sprintf("Bearer %s", g.UserToken.AccessToken)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    80
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    81
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    82
	req = rest.Request{
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    83
		BaseURL:     endPoint,
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    84
		Headers:     hdrs,
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    85
		Method:      method,
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    86
		QueryParams: params,
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    87
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    88
	return
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    89
}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    90
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    91
// apiCall makes a call to the Mastodon API server
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    92
func (g *Client) apiCall(endPoint string, method rest.Method, params apiCallParams, data interface{}) error {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    93
	// Prepare query
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    94
	req := g.prepareRequest(endPoint, method, params)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    95
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    96
	// Make API call
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    97
	r, err := restAPI(req)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    98
	if err != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
    99
		return fmt.Errorf("API query (%s) failed: %s", endPoint, err.Error())
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   100
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   101
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   102
	// Check for error reply
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   103
	var errorResult Error
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   104
	if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   105
		// The empty object is not an error
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   106
		if errorResult.Text != "" {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   107
			return fmt.Errorf("%s", errorResult.Text)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   108
		}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   109
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   110
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   111
	// Not an error reply; let's unmarshal the data
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   112
	err = json.Unmarshal([]byte(r.Body), &data)
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   113
	if err != nil {
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   114
		return fmt.Errorf("cannot decode API response (%s): %s", method, err.Error())
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   115
	}
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   116
	return nil
2bbb72b9ebf6 Rework the API wrappers to handle arrays of parameters
Mikael Berthe <mikael@lilotux.net>
parents:
diff changeset
   117
}