-
Notifications
You must be signed in to change notification settings - Fork 149
/
https_writer.go
99 lines (86 loc) · 2.33 KB
/
https_writer.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
//
// Forked and simplified from http://golang.org/src/pkg/log/syslog/syslog.go
// Fork needed to set the proper hostname in the write() function
//
package syslogwriter
import (
"crypto/tls"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"plumbing"
"strings"
"sync"
"time"
)
type httpsWriter struct {
appId string
outputUrl *url.URL
mu sync.Mutex // guards lastError
TlsConfig *tls.Config
client *http.Client
lastError error
}
func NewHttpsWriter(outputUrl *url.URL, appId string, skipCertVerify bool, dialer *net.Dialer, timeout time.Duration) (w *httpsWriter, err error) {
if dialer == nil {
return nil, errors.New("cannot construct a writer with a nil dialer")
}
if outputUrl.Scheme != "https" {
return nil, errors.New(fmt.Sprintf("Invalid scheme %s, httpsWriter only supports https", outputUrl.Scheme))
}
tlsConfig := plumbing.NewTLSConfig()
tlsConfig.InsecureSkipVerify = skipCertVerify
tr := &http.Transport{
MaxIdleConnsPerHost: 1,
TLSClientConfig: tlsConfig,
TLSHandshakeTimeout: dialer.Timeout * 2,
Dial: func(network, addr string) (net.Conn, error) {
return dialer.Dial(network, addr)
},
}
client := &http.Client{Transport: tr, Timeout: timeout}
return &httpsWriter{
appId: appId,
outputUrl: outputUrl,
TlsConfig: tlsConfig,
client: client,
}, nil
}
func (w *httpsWriter) Connect() error {
w.mu.Lock()
defer w.mu.Unlock()
if w.lastError != nil {
err := w.lastError
w.lastError = nil
return err
}
return nil
}
func (w *httpsWriter) Write(p int, b []byte, source string, sourceId string, timestamp int64) (int, error) {
syslogMsg := createMessage(p, w.appId, source, sourceId, b, timestamp)
bytesWritten, err := w.writeHttp(syslogMsg)
w.mu.Lock()
w.lastError = err
w.mu.Unlock()
return bytesWritten, err
}
func (w *httpsWriter) Close() error {
return nil
}
func (w *httpsWriter) writeHttp(finalMsg string) (byteCount int, err error) {
resp, err := w.client.Post(w.outputUrl.String(), "text/plain", strings.NewReader(finalMsg))
byteCount = len(finalMsg)
if err != nil {
return byteCount, errors.New("syslog https writer: failed to connect")
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
err = errors.New("Syslog Writer: Post responded with a non 2XX status code")
}
io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()
return byteCount, err
}