/
protocol.go
91 lines (76 loc) · 1.92 KB
/
protocol.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
package splunk
import (
"context"
"io"
"net/http"
"net/url"
uuid "github.com/satori/go.uuid"
)
type hecClient struct {
token string
serverURL *url.URL
idGen uuid.UUID
}
func newHecClient(serverURL string, token string) (*hecClient, error) {
u, err := url.Parse(serverURL)
if err != nil {
return nil, err
}
id, err := uuid.NewV4()
if err != nil {
return nil, err
}
cl := hecClient{token: token, serverURL: u, idGen: id}
return &cl, nil
}
const rawEndpointStr = "services/collector"
var rawEndpoint *url.URL
func init() {
var err error
rawEndpoint, err = url.Parse(rawEndpointStr)
if err != nil {
panic(err)
}
}
// newRequest creates a new streaming HEC raw request and returns the
// writer to it. The request is submitted when the writer is closed.
func (c *hecClient) newRequest() *hecRequest {
req := &hecRequest{url: c.url(c.idGen.String()), authHeader: c.authHeader()}
req.r, req.w = io.Pipe()
return req
}
type hecRequest struct {
r io.ReadCloser
w io.WriteCloser
url string
authHeader string
}
func (r *hecRequest) Start(ctx context.Context) (*http.Request, io.Writer, error) {
req, err := http.NewRequest("POST", r.url, r.r)
if err != nil {
return nil, nil, err
}
req.Header.Add("Authorization", r.authHeader)
req = req.WithContext(ctx)
return req, r.w, nil
}
func (r *hecRequest) Close() error {
return r.w.Close()
}
func (c *hecClient) url(channel string) string {
endpoint := c.serverURL.ResolveReference(rawEndpoint)
q := endpoint.Query()
q.Add("channel", channel)
endpoint.RawQuery = q.Encode()
return endpoint.String()
}
func (c *hecClient) authHeader() string {
return "Splunk " + c.token
}
// Response represents the JSON-parseable response from a splunk HEC
// server.
type Response struct {
Text string `json:"text,omitempty"`
Code int `json:"code"`
InvalidEventNumber *int `json:"invalid-event-number,omitempty"`
}