forked from writeas/go-writeas
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwriteas.go
171 lines (144 loc) · 4.27 KB
/
writeas.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Package writeas provides the binding for the Write.as API
package writeas
import (
"bytes"
"code.as/core/socks"
"encoding/json"
"fmt"
"github.com/writeas/impart"
"io"
"net/http"
"time"
)
const (
apiURL = "https://write.as/api"
devAPIURL = "https://development.write.as/api"
torAPIURL = "http://writeas7pm7rcdqg.onion/api"
)
// Client is used to interact with the Write.as API. It can be used to make
// authenticated or unauthenticated calls.
type Client struct {
baseURL string
// Access token for the user making requests.
token string
// Client making requests to the API
client *http.Client
// UserAgent overrides the default User-Agent header
UserAgent string
}
// defaultHTTPTimeout is the default http.Client timeout.
const defaultHTTPTimeout = 10 * time.Second
// NewClient creates a new API client. By default, all requests are made
// unauthenticated. To optionally make authenticated requests, call `SetToken`.
//
// c := writeas.NewClient()
// c.SetToken("00000000-0000-0000-0000-000000000000")
func NewClient() *Client {
return &Client{
client: &http.Client{Timeout: defaultHTTPTimeout},
baseURL: apiURL,
}
}
// NewTorClient creates a new API client for communicating with the Write.as
// Tor hidden service, using the given port to connect to the local SOCKS
// proxy.
func NewTorClient(port int) *Client {
dialSocksProxy := socks.DialSocksProxy(socks.SOCKS5, fmt.Sprintf("127.0.0.1:%d", port))
transport := &http.Transport{Dial: dialSocksProxy}
return &Client{
client: &http.Client{Transport: transport},
baseURL: torAPIURL,
}
}
// NewDevClient creates a new API client for development and testing. It'll
// communicate with our development servers, and SHOULD NOT be used in
// production.
func NewDevClient() *Client {
return &Client{
client: &http.Client{Timeout: defaultHTTPTimeout},
baseURL: devAPIURL,
}
}
// SetToken sets the user token for all future Client requests. Setting this to
// an empty string will change back to unauthenticated requests.
func (c *Client) SetToken(token string) {
c.token = token
}
// Token returns the user token currently set to the Client.
func (c *Client) Token() string {
return c.token
}
func (c *Client) get(path string, r interface{}) (*impart.Envelope, error) {
method := "GET"
if method != "GET" && method != "HEAD" {
return nil, fmt.Errorf("Method %s not currently supported by library (only HEAD and GET).\n", method)
}
return c.request(method, path, nil, r)
}
func (c *Client) post(path string, data, r interface{}) (*impart.Envelope, error) {
b := new(bytes.Buffer)
json.NewEncoder(b).Encode(data)
return c.request("POST", path, b, r)
}
func (c *Client) put(path string, data, r interface{}) (*impart.Envelope, error) {
b := new(bytes.Buffer)
json.NewEncoder(b).Encode(data)
return c.request("PUT", path, b, r)
}
func (c *Client) delete(path string, data map[string]string) (*impart.Envelope, error) {
r, err := c.buildRequest("DELETE", path, nil)
if err != nil {
return nil, err
}
q := r.URL.Query()
for k, v := range data {
q.Add(k, v)
}
r.URL.RawQuery = q.Encode()
return c.doRequest(r, nil)
}
func (c *Client) request(method, path string, data io.Reader, result interface{}) (*impart.Envelope, error) {
r, err := c.buildRequest(method, path, data)
if err != nil {
return nil, err
}
return c.doRequest(r, result)
}
func (c *Client) buildRequest(method, path string, data io.Reader) (*http.Request, error) {
url := fmt.Sprintf("%s%s", c.baseURL, path)
r, err := http.NewRequest(method, url, data)
if err != nil {
return nil, fmt.Errorf("Create request: %v", err)
}
c.prepareRequest(r)
return r, nil
}
func (c *Client) doRequest(r *http.Request, result interface{}) (*impart.Envelope, error) {
resp, err := c.client.Do(r)
if err != nil {
return nil, fmt.Errorf("Request: %v", err)
}
defer resp.Body.Close()
env := &impart.Envelope{
Code: resp.StatusCode,
}
if result != nil {
env.Data = result
err = json.NewDecoder(resp.Body).Decode(&env)
if err != nil {
return nil, err
}
}
return env, nil
}
func (c *Client) prepareRequest(r *http.Request) {
ua := c.UserAgent
if ua == "" {
ua = "go-writeas v1"
}
r.Header.Add("User-Agent", ua)
r.Header.Add("Content-Type", "application/json")
if c.token != "" {
r.Header.Add("Authorization", "Token "+c.token)
}
}