fix(inputs.http_response): Fix for IPv4 and IPv6 addresses when interface is set (#15496)
This commit is contained in:
parent
caa0cf3a80
commit
fc3cbb8256
|
|
@ -323,6 +323,8 @@ following works:
|
||||||
- github.com/russross/blackfriday [BSD 2-Clause "Simplified" License](https://github.com/russross/blackfriday/blob/master/LICENSE.txt)
|
- github.com/russross/blackfriday [BSD 2-Clause "Simplified" License](https://github.com/russross/blackfriday/blob/master/LICENSE.txt)
|
||||||
- github.com/safchain/ethtool [Apache License 2.0](https://github.com/safchain/ethtool/blob/master/LICENSE)
|
- github.com/safchain/ethtool [Apache License 2.0](https://github.com/safchain/ethtool/blob/master/LICENSE)
|
||||||
- github.com/samber/lo [MIT License](https://github.com/samber/lo/blob/master/LICENSE)
|
- github.com/samber/lo [MIT License](https://github.com/samber/lo/blob/master/LICENSE)
|
||||||
|
- github.com/seancfoley/bintree [Apache License 2.0](https://github.com/seancfoley/bintree/blob/master/LICENSE)
|
||||||
|
- github.com/seancfoley/ipaddress-go [Apache License 2.0](https://github.com/seancfoley/ipaddress-go/blob/master/LICENSE)
|
||||||
- github.com/shirou/gopsutil [BSD 3-Clause Clear License](https://github.com/shirou/gopsutil/blob/master/LICENSE)
|
- github.com/shirou/gopsutil [BSD 3-Clause Clear License](https://github.com/shirou/gopsutil/blob/master/LICENSE)
|
||||||
- github.com/shoenig/go-m1cpu [Mozilla Public License 2.0](https://github.com/shoenig/go-m1cpu/blob/main/LICENSE)
|
- github.com/shoenig/go-m1cpu [Mozilla Public License 2.0](https://github.com/shoenig/go-m1cpu/blob/main/LICENSE)
|
||||||
- github.com/shopspring/decimal [MIT License](https://github.com/shopspring/decimal/blob/master/LICENSE)
|
- github.com/shopspring/decimal [MIT License](https://github.com/shopspring/decimal/blob/master/LICENSE)
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -169,6 +169,7 @@ require (
|
||||||
github.com/robinson/gos7 v0.0.0-20240315073918-1f14519e4846
|
github.com/robinson/gos7 v0.0.0-20240315073918-1f14519e4846
|
||||||
github.com/safchain/ethtool v0.3.0
|
github.com/safchain/ethtool v0.3.0
|
||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||||
|
github.com/seancfoley/ipaddress-go v1.6.0
|
||||||
github.com/sensu/sensu-go/api/core/v2 v2.16.0
|
github.com/sensu/sensu-go/api/core/v2 v2.16.0
|
||||||
github.com/shirou/gopsutil/v3 v3.24.4
|
github.com/shirou/gopsutil/v3 v3.24.4
|
||||||
github.com/showwin/speedtest-go v1.7.7
|
github.com/showwin/speedtest-go v1.7.7
|
||||||
|
|
@ -437,6 +438,7 @@ require (
|
||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/samber/lo v1.38.1 // indirect
|
github.com/samber/lo v1.38.1 // indirect
|
||||||
|
github.com/seancfoley/bintree v1.3.1 // indirect
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3 // indirect
|
github.com/signalfx/com_signalfx_metrics_protobuf v0.0.3 // indirect
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -2113,6 +2113,10 @@ github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21 h1:yWfiTPwYxB0l5fGMhl/G+liULu
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.21/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||||
|
github.com/seancfoley/bintree v1.3.1 h1:cqmmQK7Jm4aw8gna0bP+huu5leVOgHGSJBEpUx3EXGI=
|
||||||
|
github.com/seancfoley/bintree v1.3.1/go.mod h1:hIUabL8OFYyFVTQ6azeajbopogQc2l5C/hiXMcemWNU=
|
||||||
|
github.com/seancfoley/ipaddress-go v1.6.0 h1:9z7yGmOnV4P2ML/dlR/kCJiv5tp8iHOOetJvxJh/R5w=
|
||||||
|
github.com/seancfoley/ipaddress-go v1.6.0/go.mod h1:TQRZgv+9jdvzHmKoPGBMxyiaVmoI0rYpfEk8Q/sL/Iw=
|
||||||
github.com/sensu/sensu-go/api/core/v2 v2.16.0 h1:HOq4rFkQ1S5ZjxmMTLc5J5mAbECrnKWvtXXbMqr3j9s=
|
github.com/sensu/sensu-go/api/core/v2 v2.16.0 h1:HOq4rFkQ1S5ZjxmMTLc5J5mAbECrnKWvtXXbMqr3j9s=
|
||||||
github.com/sensu/sensu-go/api/core/v2 v2.16.0/go.mod h1:MjM7+MCGEyTAgaZ589SiGHwYiaYF7N/58dU0J070u/0=
|
github.com/sensu/sensu-go/api/core/v2 v2.16.0/go.mod h1:MjM7+MCGEyTAgaZ589SiGHwYiaYF7N/58dU0J070u/0=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/benbjohnson/clock"
|
"github.com/benbjohnson/clock"
|
||||||
|
"github.com/seancfoley/ipaddress-go/ipaddr"
|
||||||
|
|
||||||
"github.com/influxdata/telegraf"
|
"github.com/influxdata/telegraf"
|
||||||
"github.com/influxdata/telegraf/config"
|
"github.com/influxdata/telegraf/config"
|
||||||
"github.com/influxdata/telegraf/internal"
|
"github.com/influxdata/telegraf/internal"
|
||||||
|
|
@ -36,40 +38,45 @@ const (
|
||||||
|
|
||||||
// HTTPResponse struct
|
// HTTPResponse struct
|
||||||
type HTTPResponse struct {
|
type HTTPResponse struct {
|
||||||
Address string `toml:"address" deprecated:"1.12.0;1.35.0;use 'urls' instead"`
|
Address string `toml:"address" deprecated:"1.12.0;1.35.0;use 'urls' instead"`
|
||||||
URLs []string `toml:"urls"`
|
URLs []string `toml:"urls"`
|
||||||
HTTPProxy string `toml:"http_proxy"`
|
HTTPProxy string `toml:"http_proxy"`
|
||||||
Body string
|
Body string `toml:"body"`
|
||||||
BodyForm map[string][]string `toml:"body_form"`
|
BodyForm map[string][]string `toml:"body_form"`
|
||||||
Method string
|
Method string `toml:"method"`
|
||||||
ResponseTimeout config.Duration
|
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||||
HTTPHeaderTags map[string]string `toml:"http_header_tags"`
|
HTTPHeaderTags map[string]string `toml:"http_header_tags"`
|
||||||
Headers map[string]string
|
Headers map[string]string `toml:"headers"`
|
||||||
FollowRedirects bool
|
FollowRedirects bool `toml:"follow_redirects"`
|
||||||
// Absolute path to file with Bearer token
|
// Absolute path to file with Bearer token
|
||||||
BearerToken string `toml:"bearer_token"`
|
BearerToken string `toml:"bearer_token"`
|
||||||
ResponseBodyField string `toml:"response_body_field"`
|
ResponseBodyField string `toml:"response_body_field"`
|
||||||
ResponseBodyMaxSize config.Size `toml:"response_body_max_size"`
|
ResponseBodyMaxSize config.Size `toml:"response_body_max_size"`
|
||||||
ResponseStringMatch string
|
ResponseStringMatch string `toml:"response_string_match"`
|
||||||
ResponseStatusCode int
|
ResponseStatusCode int `toml:"response_status_code"`
|
||||||
Interface string
|
Interface string `toml:"interface"`
|
||||||
// HTTP Basic Auth Credentials
|
// HTTP Basic Auth Credentials
|
||||||
Username config.Secret `toml:"username"`
|
Username config.Secret `toml:"username"`
|
||||||
Password config.Secret `toml:"password"`
|
Password config.Secret `toml:"password"`
|
||||||
tls.ClientConfig
|
tls.ClientConfig
|
||||||
cookie.CookieAuthConfig
|
cookie.CookieAuthConfig
|
||||||
|
|
||||||
Log telegraf.Logger
|
Log telegraf.Logger `toml:"-"`
|
||||||
|
|
||||||
compiledStringMatch *regexp.Regexp
|
compiledStringMatch *regexp.Regexp
|
||||||
client httpClient
|
clients []client
|
||||||
|
}
|
||||||
|
|
||||||
|
type client struct {
|
||||||
|
httpClient httpClient
|
||||||
|
address string
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpClient interface {
|
type httpClient interface {
|
||||||
Do(req *http.Request) (*http.Response, error)
|
Do(req *http.Request) (*http.Response, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the proxy. A configured proxy overwrites the system wide proxy.
|
// Set the proxy. A configured proxy overwrites the system-wide proxy.
|
||||||
func getProxyFunc(httpProxy string) func(*http.Request) (*url.URL, error) {
|
func getProxyFunc(httpProxy string) func(*http.Request) (*url.URL, error) {
|
||||||
if httpProxy == "" {
|
if httpProxy == "" {
|
||||||
return http.ProxyFromEnvironment
|
return http.ProxyFromEnvironment
|
||||||
|
|
@ -85,9 +92,9 @@ func getProxyFunc(httpProxy string) func(*http.Request) (*url.URL, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// createHTTPClient creates an http client which will timeout at the specified
|
// createHTTPClient creates an http client which will time out at the specified
|
||||||
// timeout period and can follow redirects if specified
|
// timeout period and can follow redirects if specified
|
||||||
func (h *HTTPResponse) createHTTPClient() (*http.Client, error) {
|
func (h *HTTPResponse) createHTTPClient(address url.URL) (*http.Client, error) {
|
||||||
tlsCfg, err := h.ClientConfig.TLSConfig()
|
tlsCfg, err := h.ClientConfig.TLSConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -96,7 +103,7 @@ func (h *HTTPResponse) createHTTPClient() (*http.Client, error) {
|
||||||
dialer := &net.Dialer{}
|
dialer := &net.Dialer{}
|
||||||
|
|
||||||
if h.Interface != "" {
|
if h.Interface != "" {
|
||||||
dialer.LocalAddr, err = localAddress(h.Interface)
|
dialer.LocalAddr, err = localAddress(h.Interface, address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +134,7 @@ func (h *HTTPResponse) createHTTPClient() (*http.Client, error) {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func localAddress(interfaceName string) (net.Addr, error) {
|
func localAddress(interfaceName string, address url.URL) (net.Addr, error) {
|
||||||
i, err := net.InterfaceByName(interfaceName)
|
i, err := net.InterfaceByName(interfaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -138,14 +145,43 @@ func localAddress(interfaceName string) (net.Addr, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
urlInIPv6, zone := isURLInIPv6(address)
|
||||||
for _, addr := range addrs {
|
for _, addr := range addrs {
|
||||||
if naddr, ok := addr.(*net.IPNet); ok {
|
if naddr, ok := addr.(*net.IPNet); ok {
|
||||||
// leaving port set to zero to let kernel pick
|
ipNetInIPv6 := isIPNetInIPv6(naddr)
|
||||||
return &net.TCPAddr{IP: naddr.IP}, nil
|
|
||||||
|
// choose interface address in the same format as server address
|
||||||
|
if ipNetInIPv6 == urlInIPv6 {
|
||||||
|
// leaving port set to zero to let kernel pick, but set zone
|
||||||
|
return &net.TCPAddr{IP: naddr.IP, Zone: zone}, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("cannot create local address for interface %q", interfaceName)
|
return nil, fmt.Errorf("cannot create local address for interface %q and server address %q", interfaceName, address.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// isURLInIPv6 returns (true, zoneName) only when URL is in IPv6 format.
|
||||||
|
// For other cases (host part of url cannot be successfully validated, doesn't contain address at all or is in IPv4 format), it returns (false, "").
|
||||||
|
func isURLInIPv6(address url.URL) (bool, string) {
|
||||||
|
host := ipaddr.NewHostName(address.Host)
|
||||||
|
if err := host.Validate(); err != nil {
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
if hostAddr := host.AsAddress(); hostAddr != nil {
|
||||||
|
if ipv6 := hostAddr.ToIPv6(); ipv6 != nil {
|
||||||
|
return true, ipv6.GetZone().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// isIPNetInIPv6 returns true only when IPNet can be represented in IPv6 format.
|
||||||
|
// For other cases (address cannot be successfully parsed or is in IPv4 format), it returns false.
|
||||||
|
func isIPNetInIPv6(address *net.IPNet) bool {
|
||||||
|
ipAddr, err := ipaddr.NewIPAddressFromNetIPNet(address)
|
||||||
|
return err == nil && ipAddr.ToIPv6() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setResult(resultString string, fields map[string]interface{}, tags map[string]string) {
|
func setResult(resultString string, fields map[string]interface{}, tags map[string]string) {
|
||||||
|
|
@ -196,10 +232,10 @@ func setError(err error, fields map[string]interface{}, tags map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPGather gathers all fields and returns any errors it encounters
|
// HTTPGather gathers all fields and returns any errors it encounters
|
||||||
func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]string, error) {
|
func (h *HTTPResponse) httpGather(cl client) (map[string]interface{}, map[string]string, error) {
|
||||||
// Prepare fields and tags
|
// Prepare fields and tags
|
||||||
fields := make(map[string]interface{})
|
fields := make(map[string]interface{})
|
||||||
tags := map[string]string{"server": u, "method": h.Method}
|
tags := map[string]string{"server": cl.address, "method": h.Method}
|
||||||
|
|
||||||
var body io.Reader
|
var body io.Reader
|
||||||
if h.Body != "" {
|
if h.Body != "" {
|
||||||
|
|
@ -214,7 +250,7 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
|
||||||
body = strings.NewReader(values.Encode())
|
body = strings.NewReader(values.Encode())
|
||||||
}
|
}
|
||||||
|
|
||||||
request, err := http.NewRequest(h.Method, u, body)
|
request, err := http.NewRequest(h.Method, cl.address, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -245,14 +281,14 @@ func (h *HTTPResponse) httpGather(u string) (map[string]interface{}, map[string]
|
||||||
|
|
||||||
// Start Timer
|
// Start Timer
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := h.client.Do(request)
|
resp, err := cl.httpClient.Do(request)
|
||||||
responseTime := time.Since(start).Seconds()
|
responseTime := time.Since(start).Seconds()
|
||||||
|
|
||||||
// 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 {
|
||||||
// Log error
|
// Log error
|
||||||
h.Log.Debugf("Network error while polling %s: %s", u, err.Error())
|
h.Log.Debugf("Network error while polling %s: %s", cl.address, err.Error())
|
||||||
|
|
||||||
// Get error details
|
// Get error details
|
||||||
if setError(err, fields, tags) == nil {
|
if setError(err, fields, tags) == nil {
|
||||||
|
|
@ -352,10 +388,9 @@ func (*HTTPResponse) SampleConfig() string {
|
||||||
return sampleConfig
|
return sampleConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather gets all metric fields and tags and returns any errors it encounters
|
func (h *HTTPResponse) Init() error {
|
||||||
func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
|
// Compile the body regex if it exists
|
||||||
// Compile the body regex if it exist
|
if h.ResponseStringMatch != "" {
|
||||||
if h.compiledStringMatch == nil {
|
|
||||||
var err error
|
var err error
|
||||||
h.compiledStringMatch, err = regexp.Compile(h.ResponseStringMatch)
|
h.compiledStringMatch, err = regexp.Compile(h.ResponseStringMatch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -367,7 +402,6 @@ func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
|
||||||
if h.ResponseTimeout < config.Duration(time.Second) {
|
if h.ResponseTimeout < config.Duration(time.Second) {
|
||||||
h.ResponseTimeout = config.Duration(time.Second * 5)
|
h.ResponseTimeout = config.Duration(time.Second * 5)
|
||||||
}
|
}
|
||||||
// Check send and expected string
|
|
||||||
if h.Method == "" {
|
if h.Method == "" {
|
||||||
h.Method = "GET"
|
h.Method = "GET"
|
||||||
}
|
}
|
||||||
|
|
@ -380,32 +414,37 @@ func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.client == nil {
|
h.clients = make([]client, 0, len(h.URLs))
|
||||||
client, err := h.createHTTPClient()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.client = client
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, u := range h.URLs {
|
for _, u := range h.URLs {
|
||||||
addr, err := url.Parse(u)
|
addr, err := url.Parse(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
acc.AddError(err)
|
return fmt.Errorf("%q is not a valid address: %w", u, err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if addr.Scheme != "http" && addr.Scheme != "https" {
|
if addr.Scheme != "http" && addr.Scheme != "https" {
|
||||||
acc.AddError(errors.New("only http and https are supported"))
|
return fmt.Errorf("%q is not a valid address: only http and https types are supported", u)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cl, err := h.createHTTPClient(*addr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
h.clients = append(h.clients, client{httpClient: cl, address: u})
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather gets all metric fields and tags and returns any errors it encounters
|
||||||
|
func (h *HTTPResponse) Gather(acc telegraf.Accumulator) error {
|
||||||
|
for _, c := range h.clients {
|
||||||
// Prepare data
|
// Prepare data
|
||||||
var fields map[string]interface{}
|
var fields map[string]interface{}
|
||||||
var tags map[string]string
|
var tags map[string]string
|
||||||
|
|
||||||
// Gather data
|
// Gather data
|
||||||
fields, tags, err = h.httpGather(u)
|
fields, tags, err := h.httpGather(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
acc.AddError(err)
|
acc.AddError(err)
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,3 @@
|
||||||
//go:build !windows
|
|
||||||
|
|
||||||
// TODO: Windows - should be enabled for Windows when https://github.com/influxdata/telegraf/issues/8451 is fixed
|
|
||||||
|
|
||||||
package http_response
|
package http_response
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -200,9 +196,10 @@ func TestHeaders(t *testing.T) {
|
||||||
"Host": "Hello",
|
"Host": "Hello",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -239,8 +236,8 @@ func TestFields(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -278,8 +275,8 @@ func TestResponseBodyField(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -313,8 +310,8 @@ func TestResponseBodyField(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"result_type": "body_read_error",
|
"result_type": "body_read_error",
|
||||||
|
|
@ -349,6 +346,7 @@ func TestResponseBodyFormField(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, h.Gather(&acc))
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
|
|
@ -387,8 +385,8 @@ func TestResponseBodyMaxSize(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"result_type": "body_read_error",
|
"result_type": "body_read_error",
|
||||||
|
|
@ -421,8 +419,8 @@ func TestHTTPHeaderTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -456,8 +454,8 @@ func TestHTTPHeaderTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedTags = map[string]interface{}{
|
expectedTags = map[string]interface{}{
|
||||||
"server": nil,
|
"server": nil,
|
||||||
|
|
@ -479,8 +477,8 @@ func TestHTTPHeaderTags(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"result_type": "connection_failed",
|
"result_type": "connection_failed",
|
||||||
|
|
@ -538,8 +536,8 @@ func TestInterface(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -574,9 +572,10 @@ func TestRedirects(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -605,9 +604,10 @@ func TestRedirects(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"result_type": "connection_failed",
|
"result_type": "connection_failed",
|
||||||
|
|
@ -642,9 +642,10 @@ func TestMethod(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -673,9 +674,10 @@ func TestMethod(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"http_response_code": http.StatusMethodNotAllowed,
|
"http_response_code": http.StatusMethodNotAllowed,
|
||||||
|
|
@ -705,9 +707,10 @@ func TestMethod(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"http_response_code": http.StatusMethodNotAllowed,
|
"http_response_code": http.StatusMethodNotAllowed,
|
||||||
|
|
@ -742,9 +745,10 @@ func TestBody(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -772,9 +776,10 @@ func TestBody(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"http_response_code": http.StatusBadRequest,
|
"http_response_code": http.StatusBadRequest,
|
||||||
|
|
@ -808,9 +813,10 @@ func TestStringMatch(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -846,9 +852,10 @@ func TestStringMatchJson(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -886,8 +893,8 @@ func TestStringMatchFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -926,9 +933,10 @@ func TestTimeout(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"result_type": "timeout",
|
"result_type": "timeout",
|
||||||
|
|
@ -962,13 +970,7 @@ func TestBadRegex(t *testing.T) {
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
require.ErrorContains(t, h.Init(), "failed to compile regular expression")
|
||||||
err := h.Gather(&acc)
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
absentFields := []string{"http_response_code", "response_time", "content_length", "response_string_match", "result_type", "result_code"}
|
|
||||||
absentTags := []string{"status_code", "result", "server", "method"}
|
|
||||||
checkOutput(t, &acc, nil, nil, absentFields, absentTags)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeClient struct {
|
type fakeClient struct {
|
||||||
|
|
@ -981,6 +983,10 @@ func (f *fakeClient) Do(_ *http.Request) (*http.Response, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNetworkErrors(t *testing.T) {
|
func TestNetworkErrors(t *testing.T) {
|
||||||
|
cl := client{
|
||||||
|
httpClient: &fakeClient{err: &url.Error{Err: &net.OpError{Err: &net.DNSError{Err: "DNS error"}}}},
|
||||||
|
address: "",
|
||||||
|
}
|
||||||
// DNS error
|
// DNS error
|
||||||
h := &HTTPResponse{
|
h := &HTTPResponse{
|
||||||
Log: testutil.Logger{},
|
Log: testutil.Logger{},
|
||||||
|
|
@ -989,12 +995,12 @@ func TestNetworkErrors(t *testing.T) {
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
ResponseTimeout: config.Duration(time.Second * 20),
|
ResponseTimeout: config.Duration(time.Second * 20),
|
||||||
FollowRedirects: false,
|
FollowRedirects: false,
|
||||||
client: &fakeClient{err: &url.Error{Err: &net.OpError{Err: &net.DNSError{Err: "DNS error"}}}},
|
clients: []client{cl},
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"result_type": "dns_error",
|
"result_type": "dns_error",
|
||||||
|
|
@ -1020,8 +1026,8 @@ func TestNetworkErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"result_type": "connection_failed",
|
"result_type": "connection_failed",
|
||||||
|
|
@ -1053,9 +1059,10 @@ func TestContentLength(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -1084,9 +1091,10 @@ func TestContentLength(t *testing.T) {
|
||||||
},
|
},
|
||||||
FollowRedirects: true,
|
FollowRedirects: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
acc = testutil.Accumulator{}
|
acc = testutil.Accumulator{}
|
||||||
err = h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields = map[string]interface{}{
|
expectedFields = map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -1116,14 +1124,14 @@ func TestRedirect(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
plugin := &HTTPResponse{
|
h := &HTTPResponse{
|
||||||
URLs: []string{ts.URL},
|
URLs: []string{ts.URL},
|
||||||
ResponseStringMatch: "test",
|
ResponseStringMatch: "test",
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := plugin.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expected := []telegraf.Metric{
|
expected := []telegraf.Metric{
|
||||||
testutil.MustMetric(
|
testutil.MustMetric(
|
||||||
|
|
@ -1175,8 +1183,8 @@ func TestBasicAuth(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -1208,8 +1216,8 @@ func TestStatusCodeMatchFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusNoContent,
|
"http_response_code": http.StatusNoContent,
|
||||||
|
|
@ -1241,8 +1249,8 @@ func TestStatusCodeMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusNoContent,
|
"http_response_code": http.StatusNoContent,
|
||||||
|
|
@ -1275,8 +1283,8 @@ func TestStatusCodeAndStringMatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
|
|
@ -1310,8 +1318,8 @@ func TestStatusCodeAndStringMatchFail(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusNoContent,
|
"http_response_code": http.StatusNoContent,
|
||||||
|
|
@ -1348,9 +1356,11 @@ func TestSNI(t *testing.T) {
|
||||||
ServerName: "super-special-hostname.example.com",
|
ServerName: "super-special-hostname.example.com",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc testutil.Accumulator
|
var acc testutil.Accumulator
|
||||||
err := h.Gather(&acc)
|
require.NoError(t, h.Init())
|
||||||
require.NoError(t, err)
|
require.NoError(t, h.Gather(&acc))
|
||||||
|
|
||||||
expectedFields := map[string]interface{}{
|
expectedFields := map[string]interface{}{
|
||||||
"http_response_code": http.StatusOK,
|
"http_response_code": http.StatusOK,
|
||||||
"result_type": "success",
|
"result_type": "success",
|
||||||
|
|
@ -1367,3 +1377,90 @@ func TestSNI(t *testing.T) {
|
||||||
absentFields := []string{"response_string_match"}
|
absentFields := []string{"response_string_match"}
|
||||||
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
checkOutput(t, &acc, expectedFields, expectedTags, absentFields, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_isURLInIPv6(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
address url.URL
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
address: parseURL(t, "http://[2001:db8:a0b:12f0::1]/index.html"),
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "http://[2001:db8:a0b:12f0::1]:80/index.html"),
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "https://[2001:db8:a0b:12f0::1%25eth0]:15000/"), // `%25` escapes `%`
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "https://2001:0db8:0001:0000:0000:0ab9:C0A8:0102"),
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "http://[2607:f8b0:4005:802::1007]/"),
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "https://127.0.0.1"),
|
||||||
|
want: false,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "https://google.com"),
|
||||||
|
want: false,
|
||||||
|
}, {
|
||||||
|
address: parseURL(t, "https://thispagemayexist.ornot/index.html"),
|
||||||
|
want: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.address.String(), func(t *testing.T) {
|
||||||
|
if got, _ := isURLInIPv6(tt.address); got != tt.want {
|
||||||
|
t.Errorf("isURLInIPv6() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_isIPNetInIPv6(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
address *net.IPNet
|
||||||
|
want bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
address: &net.IPNet{
|
||||||
|
IP: net.IPv4(127, 0, 0, 1),
|
||||||
|
Mask: net.CIDRMask(8, 32),
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
}, {
|
||||||
|
address: &net.IPNet{
|
||||||
|
IP: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
Mask: net.CIDRMask(128, 128),
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
address: &net.IPNet{
|
||||||
|
IP: net.IPv4(192, 168, 0, 1),
|
||||||
|
Mask: net.CIDRMask(24, 32),
|
||||||
|
},
|
||||||
|
want: false,
|
||||||
|
}, {
|
||||||
|
address: &net.IPNet{
|
||||||
|
IP: net.ParseIP("fe80::43ac:7835:471a:faba"),
|
||||||
|
Mask: net.CIDRMask(64, 128),
|
||||||
|
},
|
||||||
|
want: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.address.String(), func(t *testing.T) {
|
||||||
|
if got := isIPNetInIPv6(tt.address); got != tt.want {
|
||||||
|
t.Errorf("isIPNetInIPv6() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseURL(t *testing.T, address string) url.URL {
|
||||||
|
u, err := url.Parse(address)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, u)
|
||||||
|
return *u
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue