Allow collection of HTTP Headers in http_response input (#7405)

This commit is contained in:
Nicolas Filotto 2020-05-27 00:52:13 +02:00 committed by GitHub
parent 40fdafe193
commit 7ef1d53551
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 0 deletions

View File

@ -47,6 +47,11 @@ This input plugin checks HTTP/HTTPS connections.
# [inputs.http_response.headers]
# 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 = "eth0"
```

View File

@ -27,6 +27,7 @@ type HTTPResponse struct {
Body string
Method string
ResponseTimeout internal.Duration
HTTPHeaderTags map[string]string `toml:"http_header_tags"`
Headers map[string]string
FollowRedirects bool
// Absolute path to file with Bearer token
@ -98,6 +99,11 @@ var sampleConfig = `
# [inputs.http_response.headers]
# 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 = "eth0"
`
@ -265,6 +271,14 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
resp, err := h.client.Do(request)
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
// HTTP error codes do not generate errors in the net/http library
if err != nil {

View File

@ -86,6 +86,11 @@ func setUpTestMux() http.Handler {
http.Redirect(w, req, "/good", http.StatusMovedPermanently)
})
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!")
})
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)
}
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) {
potential, _ := net.Interfaces()