This repository was archived by the owner on Nov 5, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathhttpclient.go
More file actions
151 lines (123 loc) · 3.75 KB
/
Copy pathhttpclient.go
File metadata and controls
151 lines (123 loc) · 3.75 KB
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
package httpclient
import (
"bytes"
"errors"
"fmt"
"log"
"net/http"
"net/url"
"strings"
)
type twitterEndpoints map[string]string
// Endpoints is a map of twitter endpoints used to manage rules and streams.
var Endpoints = make(twitterEndpoints)
type (
// IHttpClient is the interface the httpClient struct implements.
IHttpClient interface {
NewHttpRequest(opts *RequestOpts) (*http.Response, error)
GetRules() (*http.Response, error)
GetSearchStream(queryParams *url.Values) (*http.Response, error)
AddRules(queryParams *url.Values, body string) (*http.Response, error)
GenerateUrl(name string, queryParams *url.Values) (string, error)
}
httpClient struct {
token string
}
)
// NewHttpClient constructs a an HttpClient to interact with twitter.
func NewHttpClient(token string) IHttpClient {
Endpoints["rules"] = "https://api.twitter.com/2/tweets/search/stream/rules"
Endpoints["stream"] = "https://api.twitter.com/2/tweets/search/stream"
Endpoints["token"] = "https://api.twitter.com/oauth2/token"
return &httpClient{token}
}
// GetRules will return the current rules available for a specific API key.
func (t *httpClient) GetRules() (*http.Response, error) {
res, err := t.NewHttpRequest(&RequestOpts{
Method: "GET",
Url: Endpoints["rules"],
Body: "",
})
return res, err
}
// AddRules will add rules for you to stream with.
func (t *httpClient) AddRules(queryParams *url.Values, body string) (*http.Response, error) {
url, err := t.GenerateUrl("rules", queryParams)
if err != nil {
return nil, err
}
res, err := t.NewHttpRequest(&RequestOpts{
Method: "POST",
Url: url,
Body: body,
})
if err != nil {
return nil, err
}
return res, nil
}
// GetSearchStream will start the stream with twitter.
func (t *httpClient) GetSearchStream(queryParams *url.Values) (*http.Response, error) {
// Make an HTTP GET request to GET /2/tweets/search/stream
url, err := t.GenerateUrl("stream", queryParams)
if err != nil {
return nil, err
}
res, err := t.NewHttpRequest(&RequestOpts{
Method: "GET",
Url: url,
})
if err != nil {
return nil, err
}
return res, nil
}
// GenerateUrl is a utility function for httpclient package to generate a valid url for api.twitter.
func (t *httpClient) GenerateUrl(name string, queryParams *url.Values) (string, error) {
var url string
if queryParams != nil {
url = Endpoints[name] + fmt.Sprintf("?%v", queryParams.Encode())
} else {
url = Endpoints[name]
}
if len(url) == 0 || !strings.HasPrefix(url, "https://api.twitter.com") {
return url, errors.New("Could not find endpoint with name " + name)
} else {
return url, nil
}
}
// NewHttpRequest performs an authenticated http request with twitter with the token this httpclient has.
func (t *httpClient) NewHttpRequest(opts *RequestOpts) (*http.Response, error) {
var req *http.Request
var err error
if opts.Method == "GET" {
req, err = http.NewRequest(opts.Method, opts.Url, nil)
} else {
bufferBody := bytes.NewBuffer([]byte(opts.Body))
req, err = http.NewRequest(opts.Method, opts.Url, bufferBody)
}
if err != nil {
log.Printf("Failed to construct http request for %s: %v", opts.Url, err)
return nil, err
}
// Set Headers
req.Header.Set("Content-Type", "application/json")
if len(opts.Headers) > 0 {
for _, header := range opts.Headers {
req.Header.Set(header.Key, header.Value)
}
}
// Set token if this httpclient has a token set
if len(t.token) > 0 {
req.Header.Set("Authorization", "Bearer "+t.token)
}
// Perform network request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Printf("Failed to perform request for %s: %v", opts.Url, err)
return nil, err
}
responseParser := new(httpResponseParser)
return responseParser.handleResponse(resp, opts, t.NewHttpRequest)
}