diff --git a/plugins/inputs/http_listener_v2/README.md b/plugins/inputs/http_listener_v2/README.md index 85e8f64934efb..d3fb6fe5f8e8f 100644 --- a/plugins/inputs/http_listener_v2/README.md +++ b/plugins/inputs/http_listener_v2/README.md @@ -18,13 +18,13 @@ This is a sample configuration for the plugin. ## Address and port to host HTTP listener on service_address = ":8080" + ## Path to listen to. + ## This is depracated and will be appended to paths + # path = "/telegraf" + ## Paths to listen to. # paths = ["/telegraf"] - ## Save path in path_tag - ## Do not include path in tag if path_tag is an empty string - # path_tag = "" - ## HTTP methods to accept. # methods = ["POST", "PUT"] diff --git a/plugins/inputs/http_listener_v2/http_listener_v2.go b/plugins/inputs/http_listener_v2/http_listener_v2.go index ff78059c752c2..f0877922fe3a4 100644 --- a/plugins/inputs/http_listener_v2/http_listener_v2.go +++ b/plugins/inputs/http_listener_v2/http_listener_v2.go @@ -15,6 +15,7 @@ import ( "github.com/golang/snappy" "github.com/influxdata/telegraf" "github.com/influxdata/telegraf/config" + "github.com/influxdata/telegraf/internal/choice" tlsint "github.com/influxdata/telegraf/plugins/common/tls" "github.com/influxdata/telegraf/plugins/inputs" "github.com/influxdata/telegraf/plugins/parsers" @@ -36,6 +37,7 @@ type TimeFunc func() time.Time // HTTPListenerV2 is an input plugin that collects external metrics sent via HTTP type HTTPListenerV2 struct { ServiceAddress string `toml:"service_address"` + Path string `toml:"path"` Paths []string `toml:"paths"` PathTag string `toml:"path_tag"` Methods []string `toml:"methods"` @@ -64,6 +66,10 @@ const sampleConfig = ` ## Address and port to host HTTP listener on service_address = ":8080" + ## Path to listen to. + ## This is depracated and will be appended to paths + # path = "/telegraf" + ## Paths to listen to. # paths = ["/telegraf"] @@ -143,6 +149,9 @@ func (h *HTTPListenerV2) Start(acc telegraf.Accumulator) error { h.PathTag = strings.TrimSpace(h.PathTag) + // Append h.Path to h.Paths + h.Paths = append(h.Paths, h.Path) + h.acc = acc tlsConf, err := h.ServerConfig.TLSConfig() @@ -193,20 +202,10 @@ func (h *HTTPListenerV2) Stop() { h.wg.Wait() } -func (h *HTTPListenerV2) containsPath(needle string) bool { - for _, v := range h.Paths { - if v == needle { - return true - } - } - - return false -} - func (h *HTTPListenerV2) ServeHTTP(res http.ResponseWriter, req *http.Request) { handler := h.serveWrite - if !h.containsPath(req.URL.Path) { + if !choice.Contains(req.URL.Path, h.Paths) { handler = http.NotFound } @@ -391,6 +390,7 @@ func init() { return &HTTPListenerV2{ ServiceAddress: ":8080", TimeFunc: time.Now, + Path: "/telegraf", Paths: []string{"/telegraf"}, Methods: []string{"POST", "PUT"}, DataSource: body, diff --git a/plugins/inputs/http_listener_v2/http_listener_v2_test.go b/plugins/inputs/http_listener_v2/http_listener_v2_test.go index 3bbe7e82efeaa..dfc3e413d96e1 100644 --- a/plugins/inputs/http_listener_v2/http_listener_v2_test.go +++ b/plugins/inputs/http_listener_v2/http_listener_v2_test.go @@ -49,7 +49,7 @@ func newTestHTTPListenerV2() *HTTPListenerV2 { listener := &HTTPListenerV2{ Log: testutil.Logger{}, ServiceAddress: "localhost:0", - Paths: []string{"/write"}, + Path: "/write", Methods: []string{"POST"}, Parser: parser, TimeFunc: time.Now, @@ -72,7 +72,7 @@ func newTestHTTPSListenerV2() *HTTPListenerV2 { listener := &HTTPListenerV2{ Log: testutil.Logger{}, ServiceAddress: "localhost:0", - Paths: []string{"/write"}, + Path: "/write", Methods: []string{"POST"}, Parser: parser, ServerConfig: *pki.TLSServerConfig(), @@ -110,7 +110,7 @@ func TestInvalidListenerConfig(t *testing.T) { listener := &HTTPListenerV2{ Log: testutil.Logger{}, ServiceAddress: "address_without_port", - Paths: []string{"/write"}, + Path: "/write", Methods: []string{"POST"}, Parser: parser, TimeFunc: time.Now, @@ -274,6 +274,40 @@ func TestWriteHTTPWithWhiteSpacesPathTag(t *testing.T) { ) } +// http listener should add request path as configured path_tag (trimming it before) +func TestWriteHTTPWithMultiplePaths(t *testing.T) { + listener := newTestHTTPListenerV2() + listener.Paths = []string{"/alternative_write"} + listener.PathTag = "path" + + acc := &testutil.Accumulator{} + require.NoError(t, listener.Start(acc)) + defer listener.Stop() + + // post single message to /write + resp, err := http.Post(createURL(listener, "http", "/write", "db=mydb"), "", bytes.NewBuffer([]byte(testMsgNoNewline))) + require.NoError(t, err) + require.NoError(t, resp.Body.Close()) + require.EqualValues(t, 204, resp.StatusCode) + + // post single message to /alternative_write + resp, err = http.Post(createURL(listener, "http", "/alternative_write", "db=mydb"), "", bytes.NewBuffer([]byte(testMsgNoNewline))) + require.NoError(t, err) + require.NoError(t, resp.Body.Close()) + require.EqualValues(t, 204, resp.StatusCode) + + acc.Wait(1) + acc.AssertContainsTaggedFields(t, "cpu_load_short", + map[string]interface{}{"value": float64(12)}, + map[string]string{"host": "server01", "path": "/write"}, + ) + + acc.AssertContainsTaggedFields(t, "cpu_load_short", + map[string]interface{}{"value": float64(12)}, + map[string]string{"host": "server01", "path": "/alternative_write"}, + ) +} + // http listener should add a newline at the end of the buffer if it's not there func TestWriteHTTPNoNewline(t *testing.T) { listener := newTestHTTPListenerV2() @@ -301,7 +335,7 @@ func TestWriteHTTPExactMaxBodySize(t *testing.T) { listener := &HTTPListenerV2{ Log: testutil.Logger{}, ServiceAddress: "localhost:0", - Paths: []string{"/write"}, + Path: "/write", Methods: []string{"POST"}, Parser: parser, MaxBodySize: config.Size(len(hugeMetric)), @@ -324,7 +358,7 @@ func TestWriteHTTPVerySmallMaxBody(t *testing.T) { listener := &HTTPListenerV2{ Log: testutil.Logger{}, ServiceAddress: "localhost:0", - Paths: []string{"/write"}, + Path: "/write", Methods: []string{"POST"}, Parser: parser, MaxBodySize: config.Size(4096),