v0.3.0: fix HTTP client leak, add tests and CI pipeline
Reuse a single long-poll HTTP client instead of creating one per Events() call (~every 30s). Make TLS skip-verify configurable via syncthing_insecure_tls. Log previously swallowed config errors. Add unit tests for all monitor trackers, config, and state logic. Add CI workflow (vet, golangci-lint, govulncheck, go test -race). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,21 +11,28 @@ import (
|
||||
|
||||
// Client talks to the Syncthing REST API.
|
||||
type Client struct {
|
||||
baseURL string
|
||||
apiKey string
|
||||
httpClient *http.Client
|
||||
baseURL string
|
||||
apiKey string
|
||||
httpClient *http.Client
|
||||
longPollClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient creates a Syncthing API client.
|
||||
func NewClient(baseURL, apiKey string) *Client {
|
||||
// When insecureTLS is true, TLS certificate verification is skipped.
|
||||
// This is the common case for local Syncthing instances that use self-signed certs.
|
||||
func NewClient(baseURL, apiKey string, insecureTLS bool) *Client {
|
||||
//nolint:gosec // Syncthing typically uses self-signed certs; controlled by config
|
||||
tlsCfg := &tls.Config{InsecureSkipVerify: insecureTLS}
|
||||
return &Client{
|
||||
baseURL: baseURL,
|
||||
apiKey: apiKey,
|
||||
httpClient: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
Timeout: 10 * time.Second,
|
||||
Transport: &http.Transport{TLSClientConfig: tlsCfg},
|
||||
},
|
||||
longPollClient: &http.Client{
|
||||
Timeout: 40 * time.Second,
|
||||
Transport: &http.Transport{TLSClientConfig: tlsCfg},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -143,13 +150,6 @@ func (c *Client) FolderStatus(folderID string) (*FolderStatus, error) {
|
||||
// Events long-polls for new events since the given ID.
|
||||
func (c *Client) Events(since int, timeout int) ([]Event, error) {
|
||||
path := fmt.Sprintf("/rest/events?since=%d&timeout=%d", since, timeout)
|
||||
// Use a longer HTTP timeout for long-polling
|
||||
client := &http.Client{
|
||||
Timeout: time.Duration(timeout+10) * time.Second,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
req, err := http.NewRequest("GET", c.baseURL+path, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -157,7 +157,7 @@ func (c *Client) Events(since int, timeout int) ([]Event, error) {
|
||||
if c.apiKey != "" {
|
||||
req.Header.Set("X-API-Key", c.apiKey)
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
resp, err := c.longPollClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user