Allow collection of HTTP Headers in http_response input (#7405)
This commit is contained in:
parent
40fdafe193
commit
7ef1d53551
|
@ -47,6 +47,11 @@ This input plugin checks HTTP/HTTPS connections.
|
||||||
# [inputs.http_response.headers]
|
# [inputs.http_response.headers]
|
||||||
# Host = "github.com"
|
# Host = "github.com"
|
||||||
|
|
||||||
|
## Optional setting to map reponse http headers into tags
|
||||||
|
## If the http header is not present on the request, no corresponding tag will be added
|
||||||
|
## If multiple instances of the http header are present, only the first value will be used
|
||||||
|
# http_header_tags = {"HTTP_HEADER" = "TAG_NAME"}
|
||||||
|
|
||||||
## Interface to use when dialing an address
|
## Interface to use when dialing an address
|
||||||
# interface = "eth0"
|
# interface = "eth0"
|
||||||
```
|
```
|
||||||
|
|
|
@ -27,6 +27,7 @@ type HTTPResponse struct {
|
||||||
Body string
|
Body string
|
||||||
Method string
|
Method string
|
||||||
ResponseTimeout internal.Duration
|
ResponseTimeout internal.Duration
|
||||||
|
HTTPHeaderTags map[string]string `toml:"http_header_tags"`
|
||||||
Headers map[string]string
|
Headers map[string]string
|
||||||
FollowRedirects bool
|
FollowRedirects bool
|
||||||
// Absolute path to file with Bearer token
|
// Absolute path to file with Bearer token
|
||||||
|
@ -98,6 +99,11 @@ var sampleConfig = `
|
||||||
# [inputs.http_response.headers]
|
# [inputs.http_response.headers]
|
||||||
# Host = "github.com"
|
# Host = "github.com"
|
||||||
|
|
||||||
|
## Optional setting to map reponse http headers into tags
|
||||||
|
## If the http header is not present on the request, no corresponding tag will be added
|
||||||
|
## If multiple instances of the http header are present, only the first value will be used
|
||||||
|
# http_header_tags = {"HTTP_HEADER" = "TAG_NAME"}
|
||||||
|
|
||||||
## Interface to use when dialing an address
|
## Interface to use when dialing an address
|
||||||
# interface = "eth0"
|
# interface = "eth0"
|
||||||
`
|
`
|
||||||
|
@ -265,6 +271,14 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
|
||||||
resp, err := h.client.Do(request)
|
resp, err := h.client.Do(request)
|
||||||
response_time := time.Since(start).Seconds()
|
response_time := time.Since(start).Seconds()
|
||||||
|
|
||||||
|
// Add the response headers
|
||||||
|
for headerName, tag := range h.HTTPHeaderTags {
|
||||||
|
headerValues, foundHeader := resp.Header[headerName]
|
||||||
|
if foundHeader && len(headerValues) > 0 {
|
||||||
|
tags[tag] = headerValues[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If an error in returned, it means we are dealing with a network error, as
|
// If an error in returned, it means we are dealing with a network error, as
|
||||||
// HTTP error codes do not generate errors in the net/http library
|
// HTTP error codes do not generate errors in the net/http library
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -86,6 +86,11 @@ func setUpTestMux() http.Handler {
|
||||||
http.Redirect(w, req, "/good", http.StatusMovedPermanently)
|
http.Redirect(w, req, "/good", http.StatusMovedPermanently)
|
||||||
})
|
})
|
||||||
mux.HandleFunc("/good", func(w http.ResponseWriter, req *http.Request) {
|
mux.HandleFunc("/good", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
w.Header().Set("Server", "MyTestServer")
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, "hit the good page!")
|
||||||
|
})
|
||||||
|
mux.HandleFunc("/noheader", func(w http.ResponseWriter, req *http.Request) {
|
||||||
fmt.Fprintf(w, "hit the good page!")
|
fmt.Fprintf(w, "hit the good page!")
|
||||||
})
|
})
|
||||||
mux.HandleFunc("/jsonresponse", func(w http.ResponseWriter, req *http.Request) {
|
mux.HandleFunc("/jsonresponse", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
@ -218,6 +223,72 @@ func TestFields(t *testing.T) {
|
||||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHTTPHeaderTags(t *testing.T) {
|
||||||
|
mux := setUpTestMux()
|
||||||
|
ts := httptest.NewServer(mux)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
h := &HTTPResponse{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
Address: ts.URL + "/good",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: internal.Duration{Duration: time.Second * 20},
|
||||||
|
HTTPHeaderTags: map[string]string{"Server": "my_server", "Content-Type": "content_type"},
|
||||||
|
Headers: map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
err := h.Gather(&acc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expectedFields := map[string]interface{}{
|
||||||
|
"http_response_code": http.StatusOK,
|
||||||
|
"result_type": "success",
|
||||||
|
"result_code": 0,
|
||||||
|
"response_time": nil,
|
||||||
|
"content_length": nil,
|
||||||
|
}
|
||||||
|
expectedTags := map[string]interface{}{
|
||||||
|
"server": nil,
|
||||||
|
"method": "GET",
|
||||||
|
"status_code": "200",
|
||||||
|
"result": "success",
|
||||||
|
"my_server": "MyTestServer",
|
||||||
|
"content_type": "application/json; charset=utf-8",
|
||||||
|
}
|
||||||
|
absentFields := []string{"response_string_match"}
|
||||||
|
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||||
|
|
||||||
|
h = &HTTPResponse{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
Address: ts.URL + "/noheader",
|
||||||
|
Body: "{ 'test': 'data'}",
|
||||||
|
Method: "GET",
|
||||||
|
ResponseTimeout: internal.Duration{Duration: time.Second * 20},
|
||||||
|
HTTPHeaderTags: map[string]string{"Server": "my_server", "Content-Type": "content_type"},
|
||||||
|
Headers: map[string]string{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
FollowRedirects: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc = testutil.Accumulator{}
|
||||||
|
err = h.Gather(&acc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expectedTags = map[string]interface{}{
|
||||||
|
"server": nil,
|
||||||
|
"method": "GET",
|
||||||
|
"status_code": "200",
|
||||||
|
"result": "success",
|
||||||
|
}
|
||||||
|
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func findInterface() (net.Interface, error) {
|
func findInterface() (net.Interface, error) {
|
||||||
potential, _ := net.Interfaces()
|
potential, _ := net.Interfaces()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue