# HTTP proxy server to use to connect to the targets.
[ proxy_url: <string> ]
+ # Skip DNS resolution and URL change when an HTTP proxy (proxy_url) is set.
+ [ skip_resolve_phase_with_proxy: <boolean> | default = false ]
+
# OAuth 2.0 configuration to use to connect to the targets.
oauth2:
[ <oauth2> ]
# The body of the HTTP request used in probe.
body: [ <string> ]
-
```
#### <http_header_match_spec>
ValidHTTPVersions []string `yaml:"valid_http_versions,omitempty"`
IPProtocol string `yaml:"preferred_ip_protocol,omitempty"`
IPProtocolFallback bool `yaml:"ip_protocol_fallback,omitempty"`
+ SkipResolvePhaseWithProxy bool `yaml:"skip_resolve_phase_with_proxy,omitempty"`
NoFollowRedirects *bool `yaml:"no_follow_redirects,omitempty"`
FailIfSSL bool `yaml:"fail_if_ssl,omitempty"`
FailIfNotSSL bool `yaml:"fail_if_not_ssl,omitempty"`
targetHost := targetURL.Hostname()
targetPort := targetURL.Port()
- ip, lookupTime, err := chooseProtocol(ctx, module.HTTP.IPProtocol, module.HTTP.IPProtocolFallback, targetHost, registry, logger)
- durationGaugeVec.WithLabelValues("resolve").Add(lookupTime)
- if err != nil {
- level.Error(logger).Log("msg", "Error resolving address", "err", err)
- return false
+ var ip *net.IPAddr
+ if !module.HTTP.SkipResolvePhaseWithProxy || module.HTTP.HTTPClientConfig.ProxyURL.URL == nil {
+ var lookupTime float64
+ ip, lookupTime, err = chooseProtocol(ctx, module.HTTP.IPProtocol, module.HTTP.IPProtocolFallback, targetHost, registry, logger)
+ durationGaugeVec.WithLabelValues("resolve").Add(lookupTime)
+ if err != nil {
+ level.Error(logger).Log("msg", "Error resolving address", "err", err)
+ return false
+ }
}
// Do not move the following variable to global scope. The cases.Caser returned by
httpConfig.Method = "GET"
}
- // Replace the host field in the URL with the IP we resolved.
origHost := targetURL.Host
- if targetPort == "" {
- if strings.Contains(ip.String(), ":") {
- targetURL.Host = "[" + ip.String() + "]"
+ if ip != nil {
+ // Replace the host field in the URL with the IP we resolved.
+ if targetPort == "" {
+ if strings.Contains(ip.String(), ":") {
+ targetURL.Host = "[" + ip.String() + "]"
+ } else {
+ targetURL.Host = ip.String()
+ }
} else {
- targetURL.Host = ip.String()
+ targetURL.Host = net.JoinHostPort(ip.String(), targetPort)
}
- } else {
- targetURL.Host = net.JoinHostPort(ip.String(), targetPort)
}
var body io.Reader
"io/ioutil"
"net/http"
"net/http/httptest"
+ "net/url"
"os"
"strconv"
"strings"
t.Fatalf("Redirect test failed unexpectedly, got %s", body)
}
}
+
+func TestSkipResolvePhase(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping network dependent test")
+ }
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusNoContent)
+ }))
+ defer ts.Close()
+
+ t.Run("Without Proxy", func(t *testing.T) {
+ registry := prometheus.NewRegistry()
+ testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ result := ProbeHTTP(testCTX, ts.URL,
+ config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, HTTPClientConfig: pconfig.DefaultHTTPClientConfig, SkipResolvePhaseWithProxy: true}}, registry, log.NewNopLogger())
+ if !result {
+ t.Fatalf("Probe unsuccessful")
+ }
+ mfs, err := registry.Gather()
+ if err != nil {
+ t.Fatal(err)
+ }
+ expectedMetrics := map[string]map[string]map[string]struct{}{
+ "probe_http_duration_seconds": {
+ "phase": {
+ "connect": {},
+ "processing": {},
+ "resolve": {},
+ "transfer": {},
+ "tls": {},
+ },
+ },
+ }
+
+ checkMetrics(expectedMetrics, mfs, t)
+ })
+ t.Run("With Proxy", func(t *testing.T) {
+ registry := prometheus.NewRegistry()
+ testCTX, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ httpCfg := pconfig.DefaultHTTPClientConfig
+ u, err := url.Parse("http://127.0.0.1:3128")
+ if err != nil {
+ t.Fatalf(err.Error())
+ }
+ httpCfg.ProxyURL = pconfig.URL{
+ URL: u,
+ }
+ ProbeHTTP(testCTX, ts.URL,
+ config.Module{Timeout: time.Second, HTTP: config.HTTPProbe{IPProtocolFallback: true, HTTPClientConfig: httpCfg, SkipResolvePhaseWithProxy: true}}, registry, log.NewNopLogger())
+ mfs, err := registry.Gather()
+ if err != nil {
+ t.Fatal(err)
+ }
+ expectedMetrics := map[string]map[string]map[string]struct{}{
+ "probe_http_duration_seconds": {
+ "phase": {
+ "connect": {},
+ "processing": {},
+ "transfer": {},
+ "tls": {},
+ },
+ },
+ }
+
+ checkMetrics(expectedMetrics, mfs, t)
+ })
+}