Go client for the Write.as API https://developers.write.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.2 KiB

  1. // Package writeas provides the binding for the Write.as API
  2. package writeas
  3. import (
  4. "bytes"
  5. "encoding/json"
  6. "fmt"
  7. "github.com/writeas/impart"
  8. "io"
  9. "net/http"
  10. "time"
  11. )
  12. const (
  13. apiURL = "https://write.as/api"
  14. )
  15. // Client is used to interact with the Write.as API. It can be used to make
  16. // authenticated or unauthenticated calls.
  17. type Client struct {
  18. baseURL string
  19. // Access token for the user making requests.
  20. token string
  21. // Client making requests to the API
  22. client *http.Client
  23. }
  24. // defaultHTTPTimeout is the default http.Client timeout.
  25. const defaultHTTPTimeout = 10 * time.Second
  26. // NewClient creates a new API client. By default, all requests are made
  27. // unauthenticated. To optionally make authenticated requests, call `SetToken`.
  28. //
  29. // c := writeas.NewClient()
  30. // c.SetToken("00000000-0000-0000-0000-000000000000")
  31. func NewClient() *Client {
  32. return &Client{
  33. client: &http.Client{Timeout: defaultHTTPTimeout},
  34. baseURL: apiURL,
  35. }
  36. }
  37. // SetToken sets the user token for all future Client requests. Setting this to
  38. // an empty string will change back to unauthenticated requests.
  39. func (c *Client) SetToken(token string) {
  40. c.token = token
  41. }
  42. func (c *Client) get(path string, r interface{}) (*impart.Envelope, error) {
  43. method := "GET"
  44. if method != "GET" && method != "HEAD" {
  45. return nil, fmt.Errorf("Method %s not currently supported by library (only HEAD and GET).\n", method)
  46. }
  47. return c.request(method, path, nil, r)
  48. }
  49. func (c *Client) post(path string, data, r interface{}) (*impart.Envelope, error) {
  50. b := new(bytes.Buffer)
  51. json.NewEncoder(b).Encode(data)
  52. return c.request("POST", path, b, r)
  53. }
  54. func (c *Client) put(path string, data, r interface{}) (*impart.Envelope, error) {
  55. b := new(bytes.Buffer)
  56. json.NewEncoder(b).Encode(data)
  57. return c.request("PUT", path, b, r)
  58. }
  59. func (c *Client) delete(path string, data map[string]string) (*impart.Envelope, error) {
  60. r, err := c.buildRequest("DELETE", path, nil)
  61. if err != nil {
  62. return nil, err
  63. }
  64. q := r.URL.Query()
  65. for k, v := range data {
  66. q.Add(k, v)
  67. }
  68. r.URL.RawQuery = q.Encode()
  69. return c.doRequest(r, nil)
  70. }
  71. func (c *Client) request(method, path string, data io.Reader, result interface{}) (*impart.Envelope, error) {
  72. r, err := c.buildRequest(method, path, data)
  73. if err != nil {
  74. return nil, err
  75. }
  76. return c.doRequest(r, result)
  77. }
  78. func (c *Client) buildRequest(method, path string, data io.Reader) (*http.Request, error) {
  79. url := fmt.Sprintf("%s%s", c.baseURL, path)
  80. r, err := http.NewRequest(method, url, data)
  81. if err != nil {
  82. return nil, fmt.Errorf("Create request: %v", err)
  83. }
  84. c.prepareRequest(r)
  85. return r, nil
  86. }
  87. func (c *Client) doRequest(r *http.Request, result interface{}) (*impart.Envelope, error) {
  88. resp, err := c.client.Do(r)
  89. if err != nil {
  90. return nil, fmt.Errorf("Request: %v", err)
  91. }
  92. defer resp.Body.Close()
  93. env := &impart.Envelope{
  94. Code: resp.StatusCode,
  95. }
  96. if result != nil {
  97. env.Data = result
  98. err = json.NewDecoder(resp.Body).Decode(&env)
  99. if err != nil {
  100. return nil, err
  101. }
  102. }
  103. return env, nil
  104. }
  105. func (c *Client) prepareRequest(r *http.Request) {
  106. r.Header.Add("User-Agent", "go-writeas v1")
  107. r.Header.Add("Content-Type", "application/json")
  108. if c.token != "" {
  109. r.Header.Add("Authorization", "Token "+c.token)
  110. }
  111. }