Copyright 2015 Google LLC. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Package http supports network connections to HTTP servers. This package is not intended for use by end developers. Use the google.golang.org/api/option package to configure API clients.
package http

import (
	
	
	
	
	
	
	
	
	

	
	
	
	
	
	
	
)

const (
	mTLSModeAlways = "always"
	mTLSModeNever  = "never"
	mTLSModeAuto   = "auto"
)
NewClient returns an HTTP client for use communicating with a Google cloud service, configured with the given ClientOptions. It also returns the endpoint for the service as specified in the options.
func ( context.Context,  ...option.ClientOption) (*http.Client, string, error) {
	,  := newSettings()
	if  != nil {
		return nil, "", 
	}
	,  := getClientCertificateSource()
	if  != nil {
		return nil, "", 
	}
	,  := getEndpoint(, )
	if  != nil {
		return nil, "", 
TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
	if .HTTPClient != nil {
		return .HTTPClient, , nil
	}
	,  := newTransport(, defaultBaseTransport(, ), )
	if  != nil {
		return nil, "", 
	}
	return &http.Client{Transport: }, , nil
}
NewTransport creates an http.RoundTripper for use communicating with a Google cloud service, configured with the given ClientOptions. Its RoundTrip method delegates to base.
func ( context.Context,  http.RoundTripper,  ...option.ClientOption) (http.RoundTripper, error) {
	,  := newSettings()
	if  != nil {
		return nil, 
	}
	if .HTTPClient != nil {
		return nil, errors.New("transport/http: WithHTTPClient passed to NewTransport")
	}
	return newTransport(, , )
}

func ( context.Context,  http.RoundTripper,  *internal.DialSettings) (http.RoundTripper, error) {
	 := &parameterTransport{
		base:          ,
		userAgent:     .UserAgent,
		quotaProject:  .QuotaProject,
		requestReason: .RequestReason,
	}
	var  http.RoundTripper = 
	 = addOCTransport(, )
	switch {
Do nothing.
	case .APIKey != "":
		 = &transport.APIKey{
			Transport: ,
			Key:       .APIKey,
		}
	default:
		,  := internal.Creds(, )
		if  != nil {
			return nil, 
		}
		if .quotaProject == "" {
			.quotaProject = internal.QuotaProjectFromCreds()
		}

		 := .TokenSource
		if .TokenSource != nil {
			 = .TokenSource
		}
		 = &oauth2.Transport{
			Base:   ,
			Source: ,
		}
	}
	return , nil
}

func ( []option.ClientOption) (*internal.DialSettings, error) {
	var  internal.DialSettings
	for ,  := range  {
		.Apply(&)
	}
	if  := .Validate();  != nil {
		return nil, 
	}
	if .GRPCConn != nil {
		return nil, errors.New("unsupported gRPC connection specified")
	}
	return &, nil
}

type parameterTransport struct {
	userAgent     string
	quotaProject  string
	requestReason string

	base http.RoundTripper
}

func ( *parameterTransport) ( *http.Request) (*http.Response, error) {
	 := .base
	if  == nil {
		return nil, errors.New("transport: no Transport specified")
	}
	 := *
	.Header = make(http.Header)
	for ,  := range .Header {
		.Header[] = 
	}
TODO(cbro): append to existing User-Agent header?
		.Header.Set("User-Agent", .userAgent)
	}
Attach system parameters into the header
	if .quotaProject != "" {
		.Header.Set("X-Goog-User-Project", .quotaProject)
	}
	if .requestReason != "" {
		.Header.Set("X-Goog-Request-Reason", .requestReason)
	}

	return .RoundTrip(&)
}
Set at init time by dial_appengine.go. If nil, we're not on App Engine.
defaultBaseTransport returns the base HTTP transport. On App Engine, this is urlfetch.Transport. Otherwise, use a default transport, taking most defaults from http.DefaultTransport. If TLSCertificate is available, set TLSClientConfig as well.
Copy http.DefaultTransport except for MaxIdleConnsPerHost setting, which is increased due to reported performance issues under load in the GCS client. Transport.Clone is only available in Go 1.13 and up.
	 := clonedTransport(http.DefaultTransport)
	if  == nil {
		 = fallbackBaseTransport()
	}
	.MaxIdleConnsPerHost = 100

	if  != nil {
		.TLSClientConfig = &tls.Config{
			GetClientCertificate: ,
		}
	}

	return 
}
fallbackBaseTransport is used in <go1.13 as well as in the rare case if http.DefaultTransport has been reassigned something that's not a *http.Transport.
getClientCertificateSource returns a default client certificate source, if not provided by the user. A nil default source can be returned if the source does not exist. Any exceptions encountered while initializing the default source will be reported as client error (ex. corrupt metadata file). The overall logic is as follows: 1. If both endpoint override and client certificate are specified, use them as is. 2. If user does not specify client certificate, we will attempt to use default client certificate. 3. If user does not specify endpoint override, we will use defaultMtlsEndpoint if client certificate is available and defaultEndpoint otherwise. Implications of the above logic: 1. If the user specifies a non-mTLS endpoint override but client certificate is available, we will pass along the cert anyway and let the server decide what to do. 2. If the user specifies an mTLS endpoint override but client certificate is not available, we will not fail-fast, but let backend throw error when connecting. We would like to avoid introducing client-side logic that parses whether the endpoint override is an mTLS url, since the url pattern may change at anytime.
func ( *internal.DialSettings) (cert.Source, error) {
	if .HTTPClient != nil {
		return nil, nil // HTTPClient is incompatible with ClientCertificateSource
	} else if .ClientCertSource != nil {
		return .ClientCertSource, nil
	} else {
		return cert.DefaultSource()
	}

}
getEndpoint returns the endpoint for the service, taking into account the user-provided endpoint override "settings.Endpoint" If no endpoint override is specified, we will either return the default endpoint or the default mTLS endpoint if a client certificate is available. You can override the default endpoint (mtls vs. regular) by setting the GOOGLE_API_USE_MTLS environment variable. If the endpoint override is an address (host:port) rather than full base URL (ex. https://...), then the user-provided address will be merged into the default endpoint. For example, WithEndpoint("myhost:8000") and WithDefaultEndpoint("https://foo.com/bar/baz") will return "https://myhost:8080/bar/baz"
func ( *internal.DialSettings,  cert.Source) (string, error) {
	if .Endpoint == "" {
		 := getMTLSMode()
		if  == mTLSModeAlways || ( != nil &&  == mTLSModeAuto) {
			return .DefaultMTLSEndpoint, nil
		}
		return .DefaultEndpoint, nil
	}
User passed in a full URL path, use it verbatim.
		return .Endpoint, nil
	}
	if .DefaultEndpoint == "" {
		return "", errors.New("WithEndpoint requires a full URL path")
	}
Assume user-provided endpoint is host[:port], merge it with the default endpoint.
	return mergeEndpoints(.DefaultEndpoint, .Endpoint)
}

func () string {
	 := os.Getenv("GOOGLE_API_USE_MTLS")
TODO(shinfan): Update this to "auto" when the mTLS feature is fully released.
		return mTLSModeNever
	}
	return strings.ToLower()
}

func (,  string) (string, error) {
	,  := url.Parse()
	if  != nil {
		return "", 
	}
	.Host = 
	return .String(), nil