@cryptotaxi247 / netdata / commits / 1d5385d15

improvement(go.d): add bearer_token_file to request cfg (#20476)

Ilya Mashchenko committed Jun 13, 2025 at 14:32 UTC 1d5385d150be823a8b9c5a7264cb3476a5aeec47
128 files changed +957 -141
src/go/plugin/go.d/collector/activemq/testdata/config.json
+1
@@ -15,6 +15,7 @@
15 },
16 "username": "ok",
17 "password": "ok",
18 + "bearer_token_file": "ok",
19 "proxy_url": "ok",
20 "proxy_username": "ok",
21 "proxy_password": "ok",
src/go/plugin/go.d/collector/activemq/testdata/config.yaml
+1
@@ -13,6 +13,7 @@ headers:
13 ok: "ok"
14 username: "ok"
15 password: "ok"
16 +bearer_token_file: "ok"
17 proxy_url: "ok"
18 proxy_username: "ok"
19 proxy_password: "ok"
src/go/plugin/go.d/collector/apache/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/apache/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/bind/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/bind/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/cassandra/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/cassandra/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9 ok: "ok"
10 username: "ok"
11 password: "ok"
12 +bearer_token_file: "ok"
13 proxy_url: "ok"
14 proxy_username: "ok"
15 proxy_password: "ok"
src/go/plugin/go.d/collector/ceph/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/ceph/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/clickhouse/collect_system_async_metrics.go
+5 -2
@@ -22,7 +22,10 @@ where
22 `
23
24 func (c *Collector) collectSystemAsyncMetrics(mx map[string]int64) error {
25 - req, _ := web.NewHTTPRequest(c.RequestConfig)
25 + req, err := web.NewHTTPRequest(c.RequestConfig)
26 + if err != nil {
27 + return err
28 + }
29 req.URL.RawQuery = makeURLQuery(querySystemAsyncMetrics)
30
31 want := map[string]float64{
@@ -35,7 +38,7 @@ func (c *Collector) collectSystemAsyncMetrics(mx map[string]int64) error {
38 var metric string
39 var n int
40
38 - err := c.doHTTP(req, func(column, value string, lineEnd bool) {
41 + err = c.doHTTP(req, func(column, value string, lineEnd bool) {
42 switch column {
43 case "metric":
44 metric = value
src/go/plugin/go.d/collector/clickhouse/collect_system_disks.go
+5 -2
@@ -26,7 +26,10 @@ type diskStats struct {
26 }
27
28 func (c *Collector) collectSystemDisks(mx map[string]int64) error {
29 - req, _ := web.NewHTTPRequest(c.RequestConfig)
29 + req, err := web.NewHTTPRequest(c.RequestConfig)
30 + if err != nil {
31 + return err
32 + }
33 req.URL.RawQuery = makeURLQuery(querySystemDisks)
34
35 seen := make(map[string]*diskStats)
@@ -42,7 +45,7 @@ func (c *Collector) collectSystemDisks(mx map[string]int64) error {
45
46 var name string
47
45 - err := c.doHTTP(req, func(column, value string, lineEnd bool) {
48 + err = c.doHTTP(req, func(column, value string, lineEnd bool) {
49 switch column {
50 case "name":
51 name = value
src/go/plugin/go.d/collector/clickhouse/collect_system_events.go
+5 -2
@@ -18,14 +18,17 @@ FROM
18 `
19
20 func (c *Collector) collectSystemEvents(mx map[string]int64) error {
21 - req, _ := web.NewHTTPRequest(c.RequestConfig)
21 + req, err := web.NewHTTPRequest(c.RequestConfig)
22 + if err != nil {
23 + return err
24 + }
25 req.URL.RawQuery = makeURLQuery(querySystemEvents)
26
27 px := "events_"
28 var event string
29 var n int
30
28 - err := c.doHTTP(req, func(column, value string, lineEnd bool) {
31 + err = c.doHTTP(req, func(column, value string, lineEnd bool) {
32 switch column {
33 case "event":
34 event = value
src/go/plugin/go.d/collector/clickhouse/collect_system_metrics.go
+5 -2
@@ -18,14 +18,17 @@ FROM
18 `
19
20 func (c *Collector) collectSystemMetrics(mx map[string]int64) error {
21 - req, _ := web.NewHTTPRequest(c.RequestConfig)
21 + req, err := web.NewHTTPRequest(c.RequestConfig)
22 + if err != nil {
23 + return err
24 + }
25 req.URL.RawQuery = makeURLQuery(querySystemMetrics)
26
27 px := "metrics_"
28 var metric string
29 var n int
30
28 - err := c.doHTTP(req, func(column, value string, lineEnd bool) {
31 + err = c.doHTTP(req, func(column, value string, lineEnd bool) {
32 switch column {
33 case "metric":
34 metric = value
src/go/plugin/go.d/collector/clickhouse/collect_system_parts.go
+5 -2
@@ -34,7 +34,10 @@ type tableStats struct {
34 }
35
36 func (c *Collector) collectSystemParts(mx map[string]int64) error {
37 - req, _ := web.NewHTTPRequest(c.RequestConfig)
37 + req, err := web.NewHTTPRequest(c.RequestConfig)
38 + if err != nil {
39 + return err
40 + }
41 req.URL.RawQuery = makeURLQuery(querySystemParts)
42
43 seen := make(map[string]*tableStats)
@@ -51,7 +54,7 @@ func (c *Collector) collectSystemParts(mx map[string]int64) error {
54
55 var database, table string
56
54 - err := c.doHTTP(req, func(column, value string, lineEnd bool) {
57 + err = c.doHTTP(req, func(column, value string, lineEnd bool) {
58 switch column {
59 case "database":
60 database = value
src/go/plugin/go.d/collector/clickhouse/collect_system_processes.go
+4 -1
@@ -16,7 +16,10 @@ FROM
16 `
17
18 func (c *Collector) collectLongestRunningQueryTime(mx map[string]int64) error {
19 - req, _ := web.NewHTTPRequest(c.RequestConfig)
19 + req, err := web.NewHTTPRequest(c.RequestConfig)
20 + if err != nil {
21 + return err
22 + }
23 req.URL.RawQuery = makeURLQuery(queryLongestQueryTime)
24
25 return c.doHTTP(req, func(column, value string, lineEnd bool) {
src/go/plugin/go.d/collector/clickhouse/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/clickhouse/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/cockroachdb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/cockroachdb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/consul/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/consul/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/coredns/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/coredns/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/couchbase/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/couchbase/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/couchdb/collect.go
+4 -1
@@ -201,7 +201,10 @@ func findMaxMQSize(MessageQueues map[string]any) int64 {
201 }
202
203 func (c *Collector) pingCouchDB() error {
204 - req, _ := web.NewHTTPRequest(c.RequestConfig)
204 + req, err := web.NewHTTPRequest(c.RequestConfig)
205 + if err != nil {
206 + return err
207 + }
208
209 var info struct{ Couchdb string }
210
src/go/plugin/go.d/collector/couchdb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/couchdb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/dnsdist/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/dnsdist/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/docker_engine/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/docker_engine/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/dockerhub/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/dockerhub/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/elasticsearch/collect.go
+4 -1
@@ -212,7 +212,10 @@ func (c *Collector) scrapeLocalIndicesStats(ms *esMetrics) {
212 }
213
214 func (c *Collector) getClusterName() (string, error) {
215 - req, _ := web.NewHTTPRequest(c.RequestConfig)
215 + req, err := web.NewHTTPRequest(c.RequestConfig)
216 + if err != nil {
217 + return "", err
218 + }
219
220 var info struct {
221 ClusterName string `json:"cluster_name"`
src/go/plugin/go.d/collector/elasticsearch/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/elasticsearch/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/envoy/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/envoy/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/fluentd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/fluentd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/geth/testdata/config.json
+1
@@ -8,6 +8,7 @@
8 },
9 "username": "ok",
10 "password": "ok",
11 + "bearer_token_file": "ok",
12 "proxy_url": "ok",
13 "proxy_username": "ok",
14 "proxy_password": "ok",
src/go/plugin/go.d/collector/geth/testdata/config.yaml
+1
@@ -6,6 +6,7 @@ headers:
6 ok: "ok"
7 username: "ok"
8 password: "ok"
9 +bearer_token_file: "ok"
10 proxy_url: "ok"
11 proxy_username: "ok"
12 proxy_password: "ok"
src/go/plugin/go.d/collector/haproxy/testdata/config.json
+1
@@ -9,6 +9,7 @@
9 },
10 "username": "ok",
11 "password": "ok",
12 + "bearer_token_file": "ok",
13 "proxy_url": "ok",
14 "proxy_username": "ok",
15 "proxy_password": "ok",
src/go/plugin/go.d/collector/haproxy/testdata/config.yaml
+1
@@ -7,6 +7,7 @@ headers:
7 ok: "ok"
8 username: "ok"
9 password: "ok"
10 +bearer_token_file: "ok"
11 proxy_url: "ok"
12 proxy_username: "ok"
13 proxy_password: "ok"
src/go/plugin/go.d/collector/hdfs/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/hdfs/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/httpcheck/testdata/config.json
+1
@@ -9,6 +9,7 @@
9 },
10 "username": "ok",
11 "password": "ok",
12 + "bearer_token_file": "ok",
13 "proxy_url": "ok",
14 "proxy_username": "ok",
15 "proxy_password": "ok",
src/go/plugin/go.d/collector/httpcheck/testdata/config.yaml
+1
@@ -7,6 +7,7 @@ headers:
7 ok: "ok"
8 username: "ok"
9 password: "ok"
10 +bearer_token_file: "ok"
11 proxy_url: "ok"
12 proxy_username: "ok"
13 proxy_password: "ok"
src/go/plugin/go.d/collector/icecast/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/icecast/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/ipfs/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/ipfs/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/k8s_kubelet/collector.go
+3 -8
@@ -35,14 +35,14 @@ func New() *Collector {
35 Config: Config{
36 HTTPConfig: web.HTTPConfig{
37 RequestConfig: web.RequestConfig{
38 - URL: "http://127.0.0.1:10255/metrics",
39 - Headers: make(map[string]string),
38 + URL: "http://127.0.0.1:10255/metrics",
39 + Headers: make(map[string]string),
40 + BearerTokenFile: "/var/run/secrets/kubernetes.io/serviceaccount/token",
41 },
42 ClientConfig: web.ClientConfig{
43 Timeout: confopt.Duration(time.Second),
44 },
45 },
45 - TokenPath: "/var/run/secrets/kubernetes.io/serviceaccount/token",
46 },
47
48 charts: charts.Copy(),
@@ -55,7 +55,6 @@ type Config struct {
55 UpdateEvery int `yaml:"update_every,omitempty" json:"update_every"`
56 AutoDetectionRetry int `yaml:"autodetection_retry,omitempty" json:"autodetection_retry"`
57 web.HTTPConfig `yaml:",inline" json:""`
58 - TokenPath string `yaml:"token_path,omitempty" json:"token_path"`
58 }
59
60 type Collector struct {
@@ -84,10 +83,6 @@ func (c *Collector) Init(context.Context) error {
83 }
84 c.prom = prom
85
87 - if tok := c.initAuthToken(); tok != "" {
88 - c.RequestConfig.Headers["Authorization"] = "Bearer " + tok
89 - }
90 -
86 return nil
87 }
88
src/go/plugin/go.d/collector/k8s_kubelet/collector_test.go
+2 -8
@@ -50,14 +50,6 @@ func TestCollector_Init(t *testing.T) {
50 assert.NoError(t, New().Init(context.Background()))
51 }
52
53 -func TestCollector_Init_ReadServiceAccountToken(t *testing.T) {
54 - collr := New()
55 - collr.TokenPath = "testdata/token.txt"
56 -
57 - assert.NoError(t, collr.Init(context.Background()))
58 - assert.Equal(t, "Bearer "+string(dataServiceAccountToken), collr.RequestConfig.Headers["Authorization"])
59 -}
60 -
53 func TestCollector_InitErrorOnCreatingClientWrongTLSCA(t *testing.T) {
54 collr := New()
55 collr.ClientConfig.TLSConfig.TLSCA = "testdata/tls"
@@ -74,6 +66,7 @@ func TestCollector_Check(t *testing.T) {
66 defer ts.Close()
67
68 collr := New()
69 + collr.BearerTokenFile = ""
70 collr.URL = ts.URL + "/metrics"
71 require.NoError(t, collr.Init(context.Background()))
72 assert.NoError(t, collr.Check(context.Background()))
@@ -95,6 +88,7 @@ func TestCollector_Collect(t *testing.T) {
88 defer ts.Close()
89
90 collr := New()
91 + collr.BearerTokenFile = ""
92 collr.URL = ts.URL + "/metrics"
93 require.NoError(t, collr.Init(context.Background()))
94 require.NoError(t, collr.Check(context.Background()))
src/go/plugin/go.d/collector/k8s_kubelet/init.go
-9
@@ -4,7 +4,6 @@ package k8s_kubelet
4
5 import (
6 "errors"
7 - "os"
7
8 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus"
9 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/web"
@@ -17,14 +16,6 @@ func (c *Collector) validateConfig() error {
16 return nil
17 }
18
20 -func (c *Collector) initAuthToken() string {
21 - bs, err := os.ReadFile(c.TokenPath)
22 - if err != nil {
23 - c.Warningf("error on reading service account token from '%s': %v", c.TokenPath, err)
24 - }
25 - return string(bs)
26 -}
27 -
19 func (c *Collector) initPrometheusClient() (prometheus.Prometheus, error) {
20 httpClient, err := web.NewHTTPClient(c.ClientConfig)
21 if err != nil {
src/go/plugin/go.d/collector/k8s_kubelet/testdata/config.json
+2 -2
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
@@ -19,6 +20,5 @@
20 "tls_cert": "ok",
21 "tls_key": "ok",
22 "tls_skip_verify": true,
22 - "force_http2": true,
23 - "token_path": "ok"
23 + "force_http2": true
24 }
src/go/plugin/go.d/collector/k8s_kubelet/testdata/config.yaml
+2 -2
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
@@ -17,5 +18,4 @@ tls_ca: "ok"
18 tls_cert: "ok"
19 tls_key: "ok"
20 tls_skip_verify: yes
20 -force_http2: yes
21 -token_path: "ok"
21 +force_http2: yes
\ No newline at end of file
src/go/plugin/go.d/collector/k8s_kubeproxy/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/k8s_kubeproxy/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/lighttpd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/lighttpd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/logstash/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/logstash/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/maxscale/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/maxscale/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/monit/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/monit/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/nats/testdata/config.json
+1
@@ -11,6 +11,7 @@
11 },
12 "username": "ok",
13 "password": "ok",
14 + "bearer_token_file": "ok",
15 "proxy_url": "ok",
16 "proxy_username": "ok",
17 "proxy_password": "ok",
src/go/plugin/go.d/collector/nats/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9 ok: "ok"
10 username: "ok"
11 password: "ok"
12 +bearer_token_file: "ok"
13 proxy_url: "ok"
14 proxy_username: "ok"
15 proxy_password: "ok"
src/go/plugin/go.d/collector/nginx/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/nginx/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/nginxplus/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/nginxplus/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/nginxunit/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/nginxunit/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/nginxvts/collect.go
+4 -1
@@ -40,7 +40,10 @@ func (c *Collector) collectServerZones(collected map[string]any, ms *vtsMetrics)
40 }
41
42 func (c *Collector) scapeVTS() (*vtsMetrics, error) {
43 - req, _ := web.NewHTTPRequest(c.RequestConfig)
43 + req, err := web.NewHTTPRequest(c.RequestConfig)
44 + if err != nil {
45 + return nil, err
46 + }
47
48 var total vtsMetrics
49 if err := web.DoHTTP(c.httpClient).RequestJSON(req, &total); err != nil {
src/go/plugin/go.d/collector/nginxvts/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/nginxvts/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/phpdaemon/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/phpdaemon/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/phpfpm/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/phpfpm/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/pihole/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/pihole/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/powerdns/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/powerdns/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/powerdns_recursor/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/powerdns_recursor/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/prometheus/collector.go
-1
@@ -55,7 +55,6 @@ type Config struct {
55 Name string `yaml:"name,omitempty" json:"name"`
56 Application string `yaml:"app,omitempty" json:"app"`
57 LabelPrefix string `yaml:"label_prefix,omitempty" json:"label_prefix"`
58 - BearerTokenFile string `yaml:"bearer_token_file,omitempty" json:"bearer_token_file"`
58 Selector selector.Expr `yaml:"selector,omitempty" json:"selector"`
59 ExpectedPrefix string `yaml:"expected_prefix,omitempty" json:"expected_prefix"`
60 MaxTS int `yaml:"max_time_series" json:"max_time_series"`
src/go/plugin/go.d/collector/prometheus/init.go
-8
@@ -5,7 +5,6 @@ package prometheus
5 import (
6 "errors"
7 "fmt"
8 - "os"
8
9 "github.com/netdata/netdata/go/plugins/pkg/matcher"
10 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/prometheus"
@@ -26,13 +25,6 @@ func (c *Collector) initPrometheusClient() (prometheus.Prometheus, error) {
25 }
26
27 req := c.RequestConfig.Copy()
29 - if c.BearerTokenFile != "" {
30 - token, err := os.ReadFile(c.BearerTokenFile)
31 - if err != nil {
32 - return nil, fmt.Errorf("bearer token file: %v", err)
33 - }
34 - req.Headers["Authorization"] = "Bearer " + string(token)
35 - }
28
29 sr, err := c.Selector.Parse()
30 if err != nil {
src/go/plugin/go.d/collector/prometheus/testdata/config.json
+1 -1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
@@ -23,7 +24,6 @@
24 "name": "ok",
25 "app": "ok",
26 "label_prefix": "ok",
26 - "bearer_token_file": "ok",
27 "selector": {
28 "allow": [
29 "ok"
src/go/plugin/go.d/collector/prometheus/testdata/config.yaml
+1 -1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
@@ -21,7 +22,6 @@ force_http2: yes
22 name: "ok"
23 app: "ok"
24 label_prefix: "ok"
24 -bearer_token_file: "ok"
25 selector:
26 allow:
27 - "ok"
src/go/plugin/go.d/collector/pulsar/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/pulsar/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/puppet/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/puppet/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/rabbitmq/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/rabbitmq/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/riakkv/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/riakkv/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/rspamd/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/rspamd/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/scaleio/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/scaleio/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/squid/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/squid/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/tengine/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/tengine/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/tomcat/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/tomcat/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/traefik/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/traefik/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/typesense/testdata/config.json
+1
@@ -11,6 +11,7 @@
11 },
12 "username": "ok",
13 "password": "ok",
14 + "bearer_token_file": "ok",
15 "proxy_url": "ok",
16 "proxy_username": "ok",
17 "proxy_password": "ok",
src/go/plugin/go.d/collector/typesense/testdata/config.yaml
+1
@@ -9,6 +9,7 @@ headers:
9 ok: "ok"
10 username: "ok"
11 password: "ok"
12 +bearer_token_file: "ok"
13 proxy_url: "ok"
14 proxy_username: "ok"
15 proxy_password: "ok"
src/go/plugin/go.d/collector/vcsa/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/vcsa/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/vernemq/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/vernemq/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/vsphere/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/vsphere/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/collector/yugabytedb/testdata/config.json
+1
@@ -10,6 +10,7 @@
10 },
11 "username": "ok",
12 "password": "ok",
13 + "bearer_token_file": "ok",
14 "proxy_url": "ok",
15 "proxy_username": "ok",
16 "proxy_password": "ok",
src/go/plugin/go.d/collector/yugabytedb/testdata/config.yaml
+1
@@ -8,6 +8,7 @@ headers:
8 ok: "ok"
9 username: "ok"
10 password: "ok"
11 +bearer_token_file: "ok"
12 proxy_url: "ok"
13 proxy_username: "ok"
14 proxy_password: "ok"
src/go/plugin/go.d/pkg/web/client_config.go
+3 -3
@@ -68,12 +68,12 @@ func NewHTTPClient(cfg ClientConfig) (*http.Client, error) {
68 func newHTTPTransport(cfg ClientConfig) (*http.Transport, error) {
69 tlsConfig, err := tlscfg.NewTLSConfig(cfg.TLSConfig)
70 if err != nil {
71 - return nil, fmt.Errorf("error on creating TLS config: %v", err)
71 + return nil, fmt.Errorf("error on creating TLS config: %w", err)
72 }
73
74 if cfg.ProxyURL != "" {
75 if _, err := url.Parse(cfg.ProxyURL); err != nil {
76 - return nil, fmt.Errorf("error on parsing proxy URL '%s': %v", cfg.ProxyURL, err)
76 + return nil, fmt.Errorf("error on parsing proxy URL '%s': %w", cfg.ProxyURL, err)
77 }
78 }
79
@@ -92,7 +92,7 @@ func newHTTPTransport(cfg ClientConfig) (*http.Transport, error) {
92 func newHTTP2Transport(cfg ClientConfig) (*http2Transport, error) {
93 tlsConfig, err := tlscfg.NewTLSConfig(cfg.TLSConfig)
94 if err != nil {
95 - return nil, fmt.Errorf("error on creating TLS config: %v", err)
95 + return nil, fmt.Errorf("error on creating TLS config: %w", err)
96 }
97
98 d := &net.Dialer{Timeout: cfg.Timeout.Duration()}
src/go/plugin/go.d/pkg/web/client_config_test.go
+442 -7
@@ -3,23 +3,458 @@
3 package web
4
5 import (
6 + "errors"
7 + "net"
8 "net/http"
9 + "net/http/httptest"
10 + "net/url"
11 + "os"
12 "testing"
13 "time"
14
15 + "golang.org/x/net/http2"
16 +
17 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/confopt"
18 + "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/tlscfg"
19
20 "github.com/stretchr/testify/assert"
21 + "github.com/stretchr/testify/require"
22 )
23
24 func TestNewHTTPClient(t *testing.T) {
16 - client, _ := NewHTTPClient(ClientConfig{
17 - Timeout: confopt.Duration(time.Second * 5),
18 - NotFollowRedirect: true,
19 - ProxyURL: "http://127.0.0.1:3128",
25 + tests := map[string]struct {
26 + config ClientConfig
27 + validate func(t *testing.T, client *http.Client, cfg ClientConfig)
28 + wantErr bool
29 + errMsg string
30 + }{
31 + "default config": {
32 + config: ClientConfig{},
33 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
34 + assert.Zero(t, client.Timeout)
35 + assert.Nil(t, client.CheckRedirect)
36 + assert.NotNil(t, client.Transport)
37 +
38 + // Verify it's using http.Transport (not http2)
39 + transport, ok := client.Transport.(*http.Transport)
40 + assert.True(t, ok)
41 + assert.NotNil(t, transport)
42 + },
43 + },
44 + "with timeout": {
45 + config: ClientConfig{
46 + Timeout: confopt.Duration(time.Second * 5),
47 + },
48 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
49 + assert.Equal(t, time.Second*5, client.Timeout)
50 +
51 + transport, ok := client.Transport.(*http.Transport)
52 + require.True(t, ok)
53 + assert.Equal(t, time.Second*5, transport.TLSHandshakeTimeout)
54 + },
55 + },
56 + "not follow redirect": {
57 + config: ClientConfig{
58 + NotFollowRedirect: true,
59 + },
60 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
61 + assert.NotNil(t, client.CheckRedirect)
62 +
63 + // Test the redirect function
64 + err := client.CheckRedirect(nil, nil)
65 + assert.Equal(t, ErrRedirectAttempted, err)
66 + },
67 + },
68 + "with proxy URL": {
69 + config: ClientConfig{
70 + ProxyURL: "http://127.0.0.1:3128",
71 + },
72 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
73 + transport, ok := client.Transport.(*http.Transport)
74 + require.True(t, ok)
75 + assert.NotNil(t, transport.Proxy)
76 +
77 + // Test proxy function
78 + req := httptest.NewRequest("GET", "http://example.com", nil)
79 + proxyURL, err := transport.Proxy(req)
80 + assert.NoError(t, err)
81 + assert.Equal(t, "http://127.0.0.1:3128", proxyURL.String())
82 + },
83 + },
84 + "invalid proxy URL": {
85 + config: ClientConfig{
86 + ProxyURL: "://invalid-url",
87 + },
88 + wantErr: true,
89 + errMsg: "error on parsing proxy URL",
90 + },
91 + "empty proxy URL uses environment": {
92 + config: ClientConfig{
93 + ProxyURL: "",
94 + },
95 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
96 + transport, ok := client.Transport.(*http.Transport)
97 + require.True(t, ok)
98 +
99 + // Set env var for testing
100 + _ = os.Setenv("HTTP_PROXY", "http://env-proxy:8080")
101 + defer func() { _ = os.Unsetenv("HTTP_PROXY") }()
102 +
103 + req := httptest.NewRequest("GET", "http://example.com", nil)
104 + proxyURL, err := transport.Proxy(req)
105 + assert.NoError(t, err)
106 + if proxyURL != nil {
107 + assert.Equal(t, "http://env-proxy:8080", proxyURL.String())
108 + }
109 + },
110 + },
111 + "force HTTP2": {
112 + config: ClientConfig{
113 + ForceHTTP2: true,
114 + },
115 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
116 + // Verify it's using http2Transport
117 + transport, ok := client.Transport.(*http2Transport)
118 + assert.True(t, ok)
119 + assert.NotNil(t, transport)
120 + assert.NotNil(t, transport.t2)
121 + assert.NotNil(t, transport.t2c)
122 + },
123 + },
124 + "with TLS config": {
125 + config: ClientConfig{
126 + TLSConfig: tlscfg.TLSConfig{
127 + InsecureSkipVerify: true,
128 + },
129 + },
130 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
131 + transport, ok := client.Transport.(*http.Transport)
132 + require.True(t, ok)
133 + assert.NotNil(t, transport.TLSClientConfig)
134 + assert.True(t, transport.TLSClientConfig.InsecureSkipVerify)
135 + },
136 + },
137 + "invalid TLS config": {
138 + config: ClientConfig{
139 + TLSConfig: tlscfg.TLSConfig{
140 + TLSCA: "/non/existent/ca.pem",
141 + TLSCert: "/non/existent/cert.pem",
142 + TLSKey: "/non/existent/key.pem",
143 + },
144 + },
145 + wantErr: true,
146 + errMsg: "error on creating TLS config",
147 + },
148 + "full config": {
149 + config: ClientConfig{
150 + Timeout: confopt.Duration(time.Second * 10),
151 + NotFollowRedirect: true,
152 + ProxyURL: "http://proxy:8080",
153 + TLSConfig: tlscfg.TLSConfig{
154 + InsecureSkipVerify: true,
155 + },
156 + },
157 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
158 + assert.Equal(t, time.Second*10, client.Timeout)
159 + assert.NotNil(t, client.CheckRedirect)
160 +
161 + transport, ok := client.Transport.(*http.Transport)
162 + require.True(t, ok)
163 + assert.True(t, transport.TLSClientConfig.InsecureSkipVerify)
164 + assert.NotNil(t, transport.Proxy)
165 + },
166 + },
167 + "HTTP2 with TLS config": {
168 + config: ClientConfig{
169 + ForceHTTP2: true,
170 + TLSConfig: tlscfg.TLSConfig{
171 + InsecureSkipVerify: true,
172 + },
173 + },
174 + validate: func(t *testing.T, client *http.Client, cfg ClientConfig) {
175 + transport, ok := client.Transport.(*http2Transport)
176 + require.True(t, ok)
177 + assert.True(t, transport.t2.TLSClientConfig.InsecureSkipVerify)
178 + assert.True(t, transport.t2c.TLSClientConfig.InsecureSkipVerify)
179 + },
180 + },
181 + }
182 +
183 + for name, test := range tests {
184 + t.Run(name, func(t *testing.T) {
185 + client, err := NewHTTPClient(test.config)
186 +
187 + if test.wantErr {
188 + assert.Error(t, err)
189 + if test.errMsg != "" {
190 + assert.Contains(t, err.Error(), test.errMsg)
191 + }
192 + assert.Nil(t, client)
193 + return
194 + }
195 +
196 + require.NoError(t, err)
197 + require.NotNil(t, client)
198 +
199 + if test.validate != nil {
200 + test.validate(t, client, test.config)
201 + }
202 + })
203 + }
204 +}
205 +
206 +func TestHTTP2Transport_RoundTrip(t *testing.T) {
207 + // Test that http2Transport can be created and has the expected structure
208 + cfg := ClientConfig{
209 + ForceHTTP2: true,
210 + TLSConfig: tlscfg.TLSConfig{
211 + InsecureSkipVerify: true,
212 + },
213 + }
214 +
215 + client, err := NewHTTPClient(cfg)
216 + require.NoError(t, err)
217 +
218 + // Verify the transport is http2Transport
219 + transport, ok := client.Transport.(*http2Transport)
220 + require.True(t, ok)
221 + assert.NotNil(t, transport.t2)
222 + assert.NotNil(t, transport.t2c)
223 +
224 + // Note: We can't easily test actual HTTP/2 communication without setting up
225 + // proper HTTP/2 servers, which httptest doesn't support directly.
226 + // The integration test with regular servers is sufficient for basic functionality.
227 +}
228 +
229 +func TestHTTP2Transport_CloseIdleConnections(t *testing.T) {
230 + transport := &http2Transport{
231 + t2: &http2.Transport{},
232 + t2c: &http2.Transport{},
233 + }
234 +
235 + // This should not panic
236 + assert.NotPanics(t, func() {
237 + transport.CloseIdleConnections()
238 })
239 +}
240 +
241 +func TestProxyFunc(t *testing.T) {
242 + tests := map[string]struct {
243 + proxyURL string
244 + envProxy string
245 + validate func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error))
246 + }{
247 + "empty proxy URL uses environment": {
248 + proxyURL: "",
249 + envProxy: "http://env-proxy:8080",
250 + validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
251 + _ = os.Setenv("HTTP_PROXY", "http://env-proxy:8080")
252 + defer func() { _ = os.Unsetenv("HTTP_PROXY") }()
253 +
254 + req := httptest.NewRequest("GET", "http://example.com", nil)
255 + proxyURL, err := proxyFunc(req)
256 + assert.NoError(t, err)
257 + if proxyURL != nil {
258 + assert.Equal(t, "http://env-proxy:8080", proxyURL.String())
259 + }
260 + },
261 + },
262 + "specific proxy URL": {
263 + proxyURL: "http://specific-proxy:3128",
264 + validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
265 + req := httptest.NewRequest("GET", "http://example.com", nil)
266 + proxyURL, err := proxyFunc(req)
267 + assert.NoError(t, err)
268 + assert.Equal(t, "http://specific-proxy:3128", proxyURL.String())
269 + },
270 + },
271 + "proxy URL with auth": {
272 + proxyURL: "http://user:pass@proxy:3128",
273 + validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
274 + req := httptest.NewRequest("GET", "http://example.com", nil)
275 + proxyURL, err := proxyFunc(req)
276 + assert.NoError(t, err)
277 + assert.Equal(t, "http://user:pass@proxy:3128", proxyURL.String())
278 + assert.Equal(t, "user", proxyURL.User.Username())
279 + pass, _ := proxyURL.User.Password()
280 + assert.Equal(t, "pass", pass)
281 + },
282 + },
283 + "https proxy URL": {
284 + proxyURL: "https://secure-proxy:443",
285 + validate: func(t *testing.T, proxyFunc func(*http.Request) (*url.URL, error)) {
286 + req := httptest.NewRequest("GET", "http://example.com", nil)
287 + proxyURL, err := proxyFunc(req)
288 + assert.NoError(t, err)
289 + assert.Equal(t, "https://secure-proxy:443", proxyURL.String())
290 + },
291 + },
292 + }
293 +
294 + for name, test := range tests {
295 + t.Run(name, func(t *testing.T) {
296 + fn := proxyFunc(test.proxyURL)
297 + assert.NotNil(t, fn)
298 +
299 + if test.validate != nil {
300 + test.validate(t, fn)
301 + }
302 + })
303 + }
304 +}
305 +
306 +func TestRedirectFunc(t *testing.T) {
307 + tests := map[string]struct {
308 + notFollow bool
309 + wantErr error
310 + }{
311 + "follow redirects": {
312 + notFollow: false,
313 + wantErr: nil,
314 + },
315 + "not follow redirects": {
316 + notFollow: true,
317 + wantErr: ErrRedirectAttempted,
318 + },
319 + }
320 +
321 + for name, test := range tests {
322 + t.Run(name, func(t *testing.T) {
323 + fn := redirectFunc(test.notFollow)
324
22 - assert.IsType(t, (*http.Client)(nil), client)
23 - assert.Equal(t, time.Second*5, client.Timeout)
24 - assert.NotNil(t, client.CheckRedirect)
325 + if test.wantErr != nil {
326 + assert.NotNil(t, fn)
327 + err := fn(nil, nil)
328 + assert.Equal(t, test.wantErr, err)
329 + } else {
330 + assert.Nil(t, fn)
331 + }
332 + })
333 + }
334 +}
335 +
336 +func TestClientIntegration(t *testing.T) {
337 + // Create a test server with various behaviors
338 + redirectCount := 0
339 + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
340 + switch r.URL.Path {
341 + case "/redirect":
342 + redirectCount++
343 + http.Redirect(w, r, "/final", http.StatusFound)
344 + case "/final":
345 + _, _ = w.Write([]byte("final destination"))
346 + case "/timeout":
347 + time.Sleep(time.Second * 2)
348 + _, _ = w.Write([]byte("too late"))
349 + default:
350 + _, _ = w.Write([]byte("default response"))
351 + }
352 + }))
353 + defer server.Close()
354 +
355 + t.Run("follow redirects", func(t *testing.T) {
356 + client, err := NewHTTPClient(ClientConfig{
357 + NotFollowRedirect: false,
358 + })
359 + require.NoError(t, err)
360 +
361 + resp, err := client.Get(server.URL + "/redirect")
362 + require.NoError(t, err)
363 + defer func() { _ = resp.Body.Close() }()
364 +
365 + assert.Equal(t, "/final", resp.Request.URL.Path)
366 + })
367 +
368 + t.Run("not follow redirects", func(t *testing.T) {
369 + client, err := NewHTTPClient(ClientConfig{
370 + NotFollowRedirect: true,
371 + })
372 + require.NoError(t, err)
373 +
374 + _, err = client.Get(server.URL + "/redirect")
375 + assert.Error(t, err)
376 +
377 + // Check if error contains redirect indication
378 + urlErr, ok := err.(*url.Error)
379 + if ok {
380 + assert.Equal(t, ErrRedirectAttempted, urlErr.Err)
381 + }
382 + })
383 +
384 + t.Run("timeout", func(t *testing.T) {
385 + client, err := NewHTTPClient(ClientConfig{
386 + Timeout: confopt.Duration(time.Millisecond * 500),
387 + })
388 + require.NoError(t, err)
389 +
390 + _, err = client.Get(server.URL + "/timeout")
391 + assert.Error(t, err)
392 +
393 + var netErr net.Error
394 + if errors.As(err, &netErr) {
395 + assert.True(t, netErr.Timeout())
396 + }
397 + })
398 +}
399 +
400 +func TestTransportWithDifferentSchemes(t *testing.T) {
401 + // Test that regular transport handles both http and https
402 + client, err := NewHTTPClient(ClientConfig{
403 + TLSConfig: tlscfg.TLSConfig{
404 + InsecureSkipVerify: true,
405 + },
406 + })
407 + require.NoError(t, err)
408 +
409 + // HTTP server
410 + httpServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
411 + _, _ = w.Write([]byte("http"))
412 + }))
413 + defer httpServer.Close()
414 +
415 + // HTTPS server
416 + httpsServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
417 + _, _ = w.Write([]byte("https"))
418 + }))
419 + defer httpsServer.Close()
420 +
421 + // Test HTTP
422 + resp, err := client.Get(httpServer.URL)
423 + require.NoError(t, err)
424 + _ = resp.Body.Close()
425 +
426 + // Test HTTPS
427 + resp, err = client.Get(httpsServer.URL)
428 + require.NoError(t, err)
429 + _ = resp.Body.Close()
430 +}
431 +
432 +func TestHTTP2TransportStructure(t *testing.T) {
433 + // Test the http2Transport structure and methods
434 + transport := &http2Transport{
435 + t2: &http2.Transport{},
436 + t2c: &http2.Transport{AllowHTTP: true},
437 + }
438 +
439 + // Test HTTPS request routing
440 + httpsReq := httptest.NewRequest("GET", "https://example.com", nil)
441 + // Just verify it doesn't panic and routes to the correct transport
442 + assert.NotPanics(t, func() {
443 + // We can't actually execute the request without a server,
444 + // but we can verify the routing logic
445 + if httpsReq.URL.Scheme == "https" {
446 + // Would use t2
447 + assert.NotNil(t, transport.t2)
448 + }
449 + })
450 +
451 + // Test HTTP request routing
452 + httpReq := httptest.NewRequest("GET", "http://example.com", nil)
453 + assert.NotPanics(t, func() {
454 + if httpReq.URL.Scheme == "http" {
455 + // Would use t2c
456 + assert.NotNil(t, transport.t2c)
457 + assert.True(t, transport.t2c.AllowHTTP)
458 + }
459 + })
460 }
src/go/plugin/go.d/pkg/web/request_config.go
+70 -7
@@ -8,10 +8,12 @@ import (
8 "io"
9 "net/http"
10 "net/url"
11 + "os"
12 "strings"
13
14 "github.com/netdata/netdata/go/plugins/pkg/buildinfo"
15 "github.com/netdata/netdata/go/plugins/pkg/executable"
16 + "github.com/netdata/netdata/go/plugins/plugin/go.d/agent/hostinfo"
17 )
18
19 // RequestConfig is the configuration of the HTTP request.
@@ -27,6 +29,11 @@ type RequestConfig struct {
29 // Password specifies the password for basic HTTPConfig authentication.
30 Password string `yaml:"password,omitempty" json:"password"`
31
32 + // BearerTokenFile specifies the path to a file containing a bearer token
33 + // to be used for HTTP authentication.
34 + // The token is read from the file and included in the Authorization header as "Bearer <token>".
35 + BearerTokenFile string `yaml:"bearer_token_file,omitempty" json:"bearer_token_file"`
36 +
37 // ProxyUsername specifies the username for basic HTTPConfig authentication.
38 // It is used to authenticate a user agent to a proxy server.
39 ProxyUsername string `yaml:"proxy_username,omitempty" json:"proxy_username"`
@@ -47,6 +54,10 @@ type RequestConfig struct {
54
55 // Copy makes a full copy of the RequestConfig.
56 func (r RequestConfig) Copy() RequestConfig {
57 + if r.Headers == nil {
58 + return r
59 + }
60 +
61 headers := make(map[string]string, len(r.Headers))
62 for k, v := range r.Headers {
63 headers[k] = v
@@ -57,22 +68,27 @@ func (r RequestConfig) Copy() RequestConfig {
68
69 var userAgent = fmt.Sprintf("Netdata %s.plugin/%s", executable.Name, buildinfo.Version)
70
60 -// NewHTTPRequest returns a new *http.Requests given a RequestConfig configuration and an error if any.
71 +// NewHTTPRequest returns a new *http.Request given a RequestConfig configuration and an error if any.
72 func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
73 var body io.Reader
74 if cfg.Body != "" {
75 body = strings.NewReader(cfg.Body)
76 }
77
67 - req, err := http.NewRequest(cfg.Method, cfg.URL, body)
78 + method := cfg.Method
79 + if method == "" {
80 + method = http.MethodGet
81 + }
82 +
83 + req, err := http.NewRequest(method, cfg.URL, body)
84 if err != nil {
85 return nil, err
86 }
87
88 req.Header.Set("User-Agent", userAgent)
89
74 - if cfg.Username != "" || cfg.Password != "" {
75 - req.SetBasicAuth(cfg.Username, cfg.Password)
90 + if err := setAuthentication(req, cfg); err != nil {
91 + return nil, err
92 }
93
94 if cfg.ProxyUsername != "" && cfg.ProxyPassword != "" {
@@ -81,8 +97,8 @@ func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
97 }
98
99 for k, v := range cfg.Headers {
84 - switch k {
85 - case "host", "Host":
100 + switch strings.ToLower(k) {
101 + case "host":
102 req.Host = v
103 default:
104 req.Header.Set(k, v)
@@ -92,18 +108,65 @@ func NewHTTPRequest(cfg RequestConfig) (*http.Request, error) {
108 return req, nil
109 }
110
111 +func setAuthentication(req *http.Request, cfg RequestConfig) error {
112 + // Priority: Bearer Token > Basic Auth
113 + switch {
114 + case cfg.BearerTokenFile != "":
115 + return setBearerTokenAuth(req, cfg.BearerTokenFile)
116 + case cfg.Username != "" || cfg.Password != "":
117 + req.SetBasicAuth(cfg.Username, cfg.Password)
118 + }
119 + return nil
120 +}
121 +
122 +func setBearerTokenAuth(req *http.Request, tokenFile string) error {
123 + tokenBs, err := os.ReadFile(tokenFile)
124 + if err != nil {
125 + // Ignore K8s service account token errors when running outside the cluster
126 + if strings.HasPrefix(tokenFile, "/var/run/secrets/") && !hostinfo.IsInsideK8sCluster() {
127 + return nil
128 + }
129 + return fmt.Errorf("bearer token file: %w", err)
130 + }
131 +
132 + token := strings.TrimSpace(string(tokenBs))
133 + if token == "" {
134 + return fmt.Errorf("bearer token file is empty")
135 + }
136 +
137 + req.Header.Set("Authorization", "Bearer "+token)
138 + return nil
139 +}
140 +
141 +// NewHTTPRequestWithPath creates a new HTTP request with the given path appended to the base URL.
142 func NewHTTPRequestWithPath(cfg RequestConfig, urlPath string) (*http.Request, error) {
143 + // Make a copy to avoid modifying the original config
144 cfg = cfg.Copy()
145
146 + // Join the paths properly
147 v, err := url.JoinPath(cfg.URL, urlPath)
148 if err != nil {
100 - return nil, fmt.Errorf("failed to join URL path: %v", err)
149 + return nil, fmt.Errorf("failed to join URL path: %w", err)
150 }
151 cfg.URL = v
152
153 return NewHTTPRequest(cfg)
154 }
155
156 +// URLQuery creates a URL-encoded query string from a single key-value pair.
157 func URLQuery(key, value string) string {
158 return url.Values{key: []string{value}}.Encode()
159 }
160 +
161 +// URLQueryMulti creates a URL-encoded query string from multiple key-value pairs.
162 +func URLQueryMulti(params map[string]string) string {
163 + if len(params) == 0 {
164 + return ""
165 + }
166 +
167 + values := url.Values{}
168 + for k, v := range params {
169 + values.Set(k, v)
170 + }
171 + return values.Encode()
172 +}
src/go/plugin/go.d/pkg/web/request_config_test.go
+284 -70
@@ -4,7 +4,10 @@ package web
4
5 import (
6 "encoding/base64"
7 + "io"
8 "net/http"
9 + "os"
10 + "path/filepath"
11 "strings"
12 "testing"
13
@@ -16,6 +19,7 @@ func TestRequest_Copy(t *testing.T) {
19 tests := map[string]struct {
20 orig RequestConfig
21 change func(req *RequestConfig)
22 + verify func(t *testing.T, orig, copy RequestConfig)
23 }{
24 "change headers": {
25 orig: RequestConfig{
@@ -32,6 +36,34 @@ func TestRequest_Copy(t *testing.T) {
36 change: func(req *RequestConfig) {
37 req.Headers["header_key"] = "header_value"
38 },
39 + verify: func(t *testing.T, orig, copy RequestConfig) {
40 + assert.Equal(t, 1, len(orig.Headers))
41 + assert.Equal(t, 2, len(copy.Headers))
42 + },
43 + },
44 + "nil headers": {
45 + orig: RequestConfig{
46 + URL: "http://127.0.0.1:19999/api/v1/info",
47 + },
48 + change: func(req *RequestConfig) {
49 + req.Headers = map[string]string{"new": "header"}
50 + },
51 + verify: func(t *testing.T, orig, copy RequestConfig) {
52 + assert.Nil(t, orig.Headers)
53 + assert.NotNil(t, copy.Headers)
54 + },
55 + },
56 + "change URL": {
57 + orig: RequestConfig{
58 + URL: "http://example.com",
59 + },
60 + change: func(req *RequestConfig) {
61 + req.URL = "http://changed.com"
62 + },
63 + verify: func(t *testing.T, orig, copy RequestConfig) {
64 + assert.Equal(t, "http://example.com", orig.URL)
65 + assert.Equal(t, "http://changed.com", copy.URL)
66 + },
67 },
68 }
69
@@ -39,73 +71,188 @@ func TestRequest_Copy(t *testing.T) {
71 t.Run(name, func(t *testing.T) {
72 reqCopy := test.orig.Copy()
73
74 + // Initial state should be equal
75 assert.Equal(t, test.orig, reqCopy)
76 +
77 + // Apply changes
78 test.change(&reqCopy)
79 +
80 + // Verify changes don't affect original
81 assert.NotEqual(t, test.orig, reqCopy)
82 +
83 + // Run custom verification if provided
84 + if test.verify != nil {
85 + test.verify(t, test.orig, reqCopy)
86 + }
87 })
88 }
89 }
90
91 func TestNewHTTPRequest(t *testing.T) {
92 + // Create a temporary file for bearer token test
93 + tmpDir := t.TempDir()
94 + bearerTokenFile := filepath.Join(tmpDir, "token")
95 + err := os.WriteFile(bearerTokenFile, []byte("test-bearer-token"), 0644)
96 + require.NoError(t, err)
97 +
98 tests := map[string]struct {
51 - req RequestConfig
52 - wantErr bool
99 + req RequestConfig
100 + validate func(t *testing.T, req *http.Request, cfg RequestConfig)
101 + wantErr bool
102 + errMsg string
103 }{
54 - "test url": {
104 + "empty config": {
105 + req: RequestConfig{},
106 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
107 + assert.Equal(t, "GET", req.Method)
108 + assert.Equal(t, "", req.URL.String())
109 + assert.NotEmpty(t, req.Header.Get("User-Agent"))
110 + },
111 + },
112 + "full config": {
113 req: RequestConfig{
56 - URL: "http://127.0.0.1:19999/api/v1/info",
114 + URL: "http://127.0.0.1:19999/api/v1/info",
115 + Method: "POST",
116 + Body: "test body content",
117 + Username: "user",
118 + Password: "pass",
119 + ProxyUsername: "proxy_user",
120 + ProxyPassword: "proxy_pass",
121 + Headers: map[string]string{
122 + "X-Custom-Header": "custom-value",
123 + "Content-Type": "application/json",
124 + },
125 + },
126 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
127 + assert.Equal(t, cfg.URL, req.URL.String())
128 + assert.Equal(t, cfg.Method, req.Method)
129 +
130 + // Check body
131 + body, err := io.ReadAll(req.Body)
132 + require.NoError(t, err)
133 + assert.Equal(t, cfg.Body, string(body))
134 +
135 + // Check basic auth
136 + user, pass, ok := req.BasicAuth()
137 + assert.True(t, ok)
138 + assert.Equal(t, cfg.Username, user)
139 + assert.Equal(t, cfg.Password, pass)
140 +
141 + // Check proxy auth
142 + proxyAuth := req.Header.Get("Proxy-Authorization")
143 + assert.NotEmpty(t, proxyAuth)
144 + proxyUser, proxyPass, ok := parseBasicAuth(proxyAuth)
145 + assert.True(t, ok)
146 + assert.Equal(t, cfg.ProxyUsername, proxyUser)
147 + assert.Equal(t, cfg.ProxyPassword, proxyPass)
148 +
149 + // Check headers
150 + for k, v := range cfg.Headers {
151 + assert.Equal(t, v, req.Header.Get(k))
152 + }
153 },
58 - wantErr: false,
154 },
60 - "test body": {
155 + "bearer token authentication": {
156 req: RequestConfig{
62 - Body: "content",
157 + URL: "http://example.com",
158 + BearerTokenFile: bearerTokenFile,
159 + },
160 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
161 + auth := req.Header.Get("Authorization")
162 + assert.Equal(t, "Bearer test-bearer-token", auth)
163 },
64 - wantErr: false,
164 },
66 - "test method": {
165 + "bearer token file not found": {
166 req: RequestConfig{
68 - Method: "POST",
167 + URL: "http://example.com",
168 + BearerTokenFile: "/non/existent/file",
169 },
70 - wantErr: false,
170 + wantErr: true,
171 + errMsg: "bearer token file",
172 },
72 - "test headers": {
173 + "bearer token takes precedence over basic auth": {
174 req: RequestConfig{
74 - Headers: map[string]string{
75 - "X-Api-Key": "secret",
76 - },
175 + URL: "http://example.com",
176 + Username: "user",
177 + Password: "pass",
178 + BearerTokenFile: bearerTokenFile,
179 + },
180 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
181 + // Should have bearer token, not basic auth
182 + auth := req.Header.Get("Authorization")
183 + assert.Equal(t, "Bearer test-bearer-token", auth)
184 +
185 + // Basic auth should not be set
186 + _, _, ok := req.BasicAuth()
187 + assert.False(t, ok)
188 },
78 - wantErr: false,
189 },
80 - "test special headers (host)": {
190 + "special headers - host lowercase": {
191 req: RequestConfig{
192 + URL: "http://example.com",
193 Headers: map[string]string{
83 - "host": "Host",
194 + "host": "custom-host.com",
195 },
196 },
86 - wantErr: false,
197 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
198 + assert.Equal(t, "custom-host.com", req.Host)
199 + // host header should not be in req.Header
200 + assert.Empty(t, req.Header.Get("host"))
201 + },
202 },
88 - "test special headers (Host)": {
203 + "special headers - Host uppercase": {
204 req: RequestConfig{
205 + URL: "http://example.com",
206 Headers: map[string]string{
91 - "Host": "Host",
207 + "Host": "custom-host.com",
208 },
209 },
94 - wantErr: false,
210 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
211 + assert.Equal(t, "custom-host.com", req.Host)
212 + assert.Empty(t, req.Header.Get("Host"))
213 + },
214 },
96 - "test username and password": {
215 + "proxy auth without username": {
216 req: RequestConfig{
98 - Username: "username",
99 - Password: "password",
217 + URL: "http://example.com",
218 + ProxyPassword: "proxy_pass",
219 + },
220 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
221 + // Proxy auth should not be set if username is missing
222 + assert.Empty(t, req.Header.Get("Proxy-Authorization"))
223 },
101 - wantErr: false,
224 },
103 - "test proxy username and proxy password": {
225 + "invalid URL": {
226 req: RequestConfig{
105 - ProxyUsername: "proxy_username",
106 - ProxyPassword: "proxy_password",
227 + URL: "://invalid-url",
228 + },
229 + wantErr: true,
230 + },
231 + "empty body": {
232 + req: RequestConfig{
233 + URL: "http://example.com",
234 + Body: "",
235 + },
236 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
237 + assert.Nil(t, req.Body)
238 + },
239 + },
240 + "default GET method": {
241 + req: RequestConfig{
242 + URL: "http://example.com",
243 + },
244 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
245 + assert.Equal(t, "GET", req.Method)
246 + },
247 + },
248 + "custom method": {
249 + req: RequestConfig{
250 + URL: "http://example.com",
251 + Method: "DELETE",
252 + },
253 + validate: func(t *testing.T, req *http.Request, cfg RequestConfig) {
254 + assert.Equal(t, "DELETE", req.Method)
255 },
108 - wantErr: false,
256 },
257 }
258
@@ -115,74 +262,141 @@ func TestNewHTTPRequest(t *testing.T) {
262
263 if test.wantErr {
264 assert.Error(t, err)
265 + if test.errMsg != "" {
266 + assert.Contains(t, err.Error(), test.errMsg)
267 + }
268 assert.Nil(t, httpReq)
269 return
270 }
271
272 require.NoError(t, err)
273 require.NotNil(t, httpReq)
124 - require.IsType(t, (*http.Request)(nil), httpReq)
125 -
126 - assert.Equal(t, test.req.URL, httpReq.URL.String())
127 -
128 - if test.req.Body != "" {
129 - assert.NotNil(t, httpReq.Body)
130 - }
274
132 - if test.req.Username != "" || test.req.Password != "" {
133 - user, pass, ok := httpReq.BasicAuth()
134 - assert.True(t, ok)
135 - assert.Equal(t, test.req.Username, user)
136 - assert.Equal(t, test.req.Password, pass)
137 - }
138 -
139 - if test.req.Method != "" {
140 - assert.Equal(t, test.req.Method, httpReq.Method)
141 - }
142 -
143 - if test.req.ProxyUsername != "" || test.req.ProxyPassword != "" {
144 - user, pass, ok := parseBasicAuth(httpReq.Header.Get("Proxy-Authorization"))
145 - assert.True(t, ok)
146 - assert.Equal(t, test.req.ProxyUsername, user)
147 - assert.Equal(t, test.req.ProxyPassword, pass)
148 - }
149 -
150 - for k, v := range test.req.Headers {
151 - switch k {
152 - case "host", "Host":
153 - assert.Equal(t, httpReq.Host, v)
154 - default:
155 - assert.Equal(t, v, httpReq.Header.Get(k))
156 - }
275 + if test.validate != nil {
276 + test.validate(t, httpReq, test.req)
277 }
278 })
279 }
280 }
281
162 -func TestNewRequest(t *testing.T) {
282 +func TestNewHTTPRequestWithPath(t *testing.T) {
283 tests := map[string]struct {
164 - url string
284 + config RequestConfig
285 path string
286 wantURL string
287 + wantErr bool
288 + errMsg string
289 }{
168 - "base url": {
169 - url: "http://127.0.0.1:65535",
290 + "base url with path": {
291 + config: RequestConfig{URL: "http://127.0.0.1:65535"},
292 path: "/bar",
293 wantURL: "http://127.0.0.1:65535/bar",
294 },
173 - "with path": {
174 - url: "http://127.0.0.1:65535/foo/",
295 + "url with trailing slash": {
296 + config: RequestConfig{URL: "http://127.0.0.1:65535/"},
297 + path: "bar",
298 + wantURL: "http://127.0.0.1:65535/bar",
299 + },
300 + "url with path and trailing slash": {
301 + config: RequestConfig{URL: "http://127.0.0.1:65535/foo/"},
302 path: "/bar",
303 wantURL: "http://127.0.0.1:65535/foo/bar",
304 },
305 + "url with path no trailing slash": {
306 + config: RequestConfig{URL: "http://127.0.0.1:65535/foo"},
307 + path: "bar",
308 + wantURL: "http://127.0.0.1:65535/foo/bar",
309 + },
310 + "empty path": {
311 + config: RequestConfig{URL: "http://example.com"},
312 + path: "",
313 + wantURL: "http://example.com",
314 + },
315 + "path with query params": {
316 + config: RequestConfig{URL: "http://example.com"},
317 + path: "/path?key=value",
318 + wantURL: "http://example.com/path%3Fkey=value", // url.JoinPath correctly escapes special chars
319 + },
320 + "complex path": {
321 + config: RequestConfig{URL: "http://example.com/api/v1"},
322 + path: "../v2/endpoint",
323 + wantURL: "http://example.com/api/v2/endpoint",
324 + },
325 + "preserve headers": {
326 + config: RequestConfig{
327 + URL: "http://example.com",
328 + Headers: map[string]string{
329 + "X-Custom": "value",
330 + },
331 + },
332 + path: "/test",
333 + wantURL: "http://example.com/test",
334 + },
335 + "invalid base URL": {
336 + config: RequestConfig{URL: "://invalid"},
337 + path: "/path",
338 + wantErr: true,
339 + },
340 }
341
342 for name, test := range tests {
343 t.Run(name, func(t *testing.T) {
182 - req, err := NewHTTPRequestWithPath(RequestConfig{URL: test.url}.Copy(), test.path)
183 - require.NoError(t, err)
344 + // Store original headers count
345 + originalHeadersCount := len(test.config.Headers)
346 +
347 + req, err := NewHTTPRequestWithPath(test.config, test.path)
348
349 + if test.wantErr {
350 + assert.Error(t, err)
351 + if test.errMsg != "" {
352 + assert.Contains(t, err.Error(), test.errMsg)
353 + }
354 + assert.Nil(t, req)
355 + return
356 + }
357 +
358 + require.NoError(t, err)
359 + require.NotNil(t, req)
360 assert.Equal(t, test.wantURL, req.URL.String())
361 +
362 + // Verify original config wasn't modified
363 + assert.Equal(t, originalHeadersCount, len(test.config.Headers))
364 + })
365 + }
366 +}
367 +
368 +func TestURLQuery(t *testing.T) {
369 + tests := map[string]struct {
370 + key string
371 + value string
372 + want string
373 + }{
374 + "simple query": {
375 + key: "foo",
376 + value: "bar",
377 + want: "foo=bar",
378 + },
379 + "empty value": {
380 + key: "key",
381 + value: "",
382 + want: "key=",
383 + },
384 + "special characters": {
385 + key: "key",
386 + value: "value with spaces & special=chars",
387 + want: "key=value+with+spaces+%26+special%3Dchars",
388 + },
389 + "unicode": {
390 + key: "name",
391 + value: "测试",
392 + want: "name=%E6%B5%8B%E8%AF%95",
393 + },
394 + }
395 +
396 + for name, test := range tests {
397 + t.Run(name, func(t *testing.T) {
398 + got := URLQuery(test.key, test.value)
399 + assert.Equal(t, test.want, got)
400 })
401 }
402 }