github.com/influxdata/influxdb/v2@v2.7.6/http/client.go (about)

     1  package http
     2  
     3  import (
     4  	"crypto/tls"
     5  	"net"
     6  	"net/http"
     7  	"net/url"
     8  	"time"
     9  
    10  	"github.com/influxdata/influxdb/v2/dbrp"
    11  	"github.com/influxdata/influxdb/v2/kit/tracing"
    12  	"github.com/influxdata/influxdb/v2/pkg/httpc"
    13  )
    14  
    15  // NewHTTPClient creates a new httpc.Client type. This call sets all
    16  // the options that are important to the http pkg on the httpc client.
    17  // The default status fn and so forth will all be set for the caller.
    18  // In addition, some options can be specified. Those will be added to the defaults.
    19  func NewHTTPClient(addr, token string, insecureSkipVerify bool, opts ...httpc.ClientOptFn) (*httpc.Client, error) {
    20  	u, err := url.Parse(addr)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  
    25  	defaultOpts := []httpc.ClientOptFn{
    26  		httpc.WithAddr(addr),
    27  		httpc.WithContentType("application/json"),
    28  		httpc.WithHTTPClient(NewClient(u.Scheme, insecureSkipVerify)),
    29  		httpc.WithInsecureSkipVerify(insecureSkipVerify),
    30  		httpc.WithStatusFn(CheckError),
    31  	}
    32  	if token != "" {
    33  		defaultOpts = append(defaultOpts, httpc.WithAuthToken(token))
    34  	}
    35  	opts = append(defaultOpts, opts...)
    36  	return httpc.New(opts...)
    37  }
    38  
    39  // Service connects to an InfluxDB via HTTP.
    40  type Service struct {
    41  	Addr               string
    42  	Token              string
    43  	InsecureSkipVerify bool
    44  
    45  	*TaskService
    46  	*NotificationRuleService
    47  	*VariableService
    48  	*WriteService
    49  	*CheckService
    50  	*NotificationEndpointService
    51  	*TelegrafService
    52  	*LabelService
    53  	DBRPMappingService *dbrp.Client
    54  }
    55  
    56  // NewService returns a service that is an HTTP client to a remote.
    57  // Address and token are needed for those services that do not use httpc.Client,
    58  // but use those for configuring.
    59  // Usually one would do:
    60  //
    61  // ```
    62  // c := NewHTTPClient(addr, token, insecureSkipVerify)
    63  // s := NewService(c, addr token)
    64  // ```
    65  //
    66  // So one should provide the same `addr` and `token` to both calls to ensure consistency
    67  // in the behavior of the returned service.
    68  func NewService(httpClient *httpc.Client, addr, token string) (*Service, error) {
    69  	return &Service{
    70  		Addr:                    addr,
    71  		Token:                   token,
    72  		TaskService:             &TaskService{Client: httpClient},
    73  		NotificationRuleService: &NotificationRuleService{Client: httpClient},
    74  		VariableService:         &VariableService{Client: httpClient},
    75  		WriteService: &WriteService{
    76  			Addr:  addr,
    77  			Token: token,
    78  		},
    79  		CheckService:                &CheckService{Client: httpClient},
    80  		NotificationEndpointService: &NotificationEndpointService{Client: httpClient},
    81  		TelegrafService:             NewTelegrafService(httpClient),
    82  		LabelService:                &LabelService{Client: httpClient},
    83  		DBRPMappingService:          dbrp.NewClient(httpClient),
    84  	}, nil
    85  }
    86  
    87  // NewURL concats addr and path.
    88  func NewURL(addr, path string) (*url.URL, error) {
    89  	u, err := url.Parse(addr)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	u.Path = path
    94  	return u, nil
    95  }
    96  
    97  // NewClient returns an http.Client that pools connections and injects a span.
    98  func NewClient(scheme string, insecure bool) *http.Client {
    99  	return httpClient(scheme, insecure)
   100  }
   101  
   102  // SpanTransport injects the http.RoundTripper.RoundTrip() request
   103  // with a span.
   104  type SpanTransport struct {
   105  	base http.RoundTripper
   106  }
   107  
   108  // RoundTrip implements the http.RoundTripper, intercepting the base
   109  // round trippers call and injecting a span.
   110  func (s *SpanTransport) RoundTrip(r *http.Request) (*http.Response, error) {
   111  	span, _ := tracing.StartSpanFromContext(r.Context())
   112  	defer span.Finish()
   113  	tracing.InjectToHTTPRequest(span, r)
   114  	return s.base.RoundTrip(r)
   115  }
   116  
   117  // DefaultTransport wraps http.DefaultTransport in SpanTransport to inject
   118  // tracing headers into all outgoing requests.
   119  var DefaultTransport http.RoundTripper = &SpanTransport{base: http.DefaultTransport}
   120  
   121  // DefaultTransportInsecure is identical to DefaultTransport, with
   122  // the exception that tls.Config is configured with InsecureSkipVerify
   123  // set to true.
   124  var DefaultTransportInsecure http.RoundTripper = &SpanTransport{
   125  	base: &http.Transport{
   126  		Proxy: http.ProxyFromEnvironment,
   127  		DialContext: (&net.Dialer{
   128  			Timeout:   30 * time.Second,
   129  			KeepAlive: 30 * time.Second,
   130  			DualStack: true,
   131  		}).DialContext,
   132  		ForceAttemptHTTP2:     true,
   133  		MaxIdleConns:          100,
   134  		IdleConnTimeout:       90 * time.Second,
   135  		TLSHandshakeTimeout:   10 * time.Second,
   136  		ExpectContinueTimeout: 1 * time.Second,
   137  		TLSClientConfig: &tls.Config{
   138  			InsecureSkipVerify: true,
   139  		},
   140  	},
   141  }
   142  
   143  func httpClient(scheme string, insecure bool) *http.Client {
   144  	if scheme == "https" && insecure {
   145  		return &http.Client{Transport: DefaultTransportInsecure}
   146  	}
   147  	return &http.Client{Transport: DefaultTransport}
   148  }