github.com/bshelton229/agent@v3.5.4+incompatible/agent/api_client.go (about)

     1  package agent
     2  
     3  import (
     4  	"bufio"
     5  	"errors"
     6  	"net"
     7  	"net/http"
     8  	"net/url"
     9  	"runtime"
    10  	"time"
    11  
    12  	"github.com/buildkite/agent/api"
    13  	"github.com/buildkite/agent/logger"
    14  	"golang.org/x/net/http2"
    15  )
    16  
    17  var debug = false
    18  
    19  type APIClient struct {
    20  	Endpoint string
    21  	Token    string
    22  }
    23  
    24  func APIClientEnableHTTPDebug() {
    25  	debug = true
    26  }
    27  
    28  func (a APIClient) Create() *api.Client {
    29  	u, err := url.Parse(a.Endpoint)
    30  	if err != nil {
    31  		logger.Warn("Failed to parse %q: %v", a.Endpoint, err)
    32  	}
    33  
    34  	if u != nil && u.Scheme == `unix` {
    35  		return a.createFromSocket(u.Path)
    36  	}
    37  
    38  	httpTransport := &http.Transport{
    39  		Proxy:              http.ProxyFromEnvironment,
    40  		DisableKeepAlives:  false,
    41  		DisableCompression: false,
    42  		Dial: (&net.Dialer{
    43  			Timeout:   30 * time.Second,
    44  			KeepAlive: 30 * time.Second,
    45  		}).Dial,
    46  		TLSHandshakeTimeout: 30 * time.Second,
    47  	}
    48  	http2.ConfigureTransport(httpTransport)
    49  
    50  	// Configure the HTTP client
    51  	httpClient := &http.Client{Transport: &api.AuthenticatedTransport{
    52  		Token:     a.Token,
    53  		Transport: httpTransport,
    54  	}}
    55  	httpClient.Timeout = 60 * time.Second
    56  
    57  	// Create the Buildkite Agent API Client
    58  	client := api.NewClient(httpClient)
    59  	client.BaseURL, _ = url.Parse(a.Endpoint)
    60  	client.UserAgent = a.UserAgent()
    61  	client.DebugHTTP = debug
    62  
    63  	return client
    64  }
    65  
    66  func (a APIClient) createFromSocket(socket string) *api.Client {
    67  	httpClient := &http.Client{
    68  		Transport: &api.AuthenticatedTransport{
    69  			Token: a.Token,
    70  			Transport: &socketTransport{
    71  				Socket:      socket,
    72  				DialTimeout: 30 * time.Second,
    73  			},
    74  		},
    75  	}
    76  
    77  	// Create the Buildkite Agent API Client
    78  	client := api.NewClient(httpClient)
    79  	client.BaseURL, _ = url.Parse(`http+unix://buildkite-agent`)
    80  	client.UserAgent = a.UserAgent()
    81  	client.DebugHTTP = debug
    82  
    83  	return client
    84  }
    85  
    86  func (a APIClient) UserAgent() string {
    87  	return "buildkite-agent/" + Version() + "." + BuildVersion() + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
    88  }
    89  
    90  // Transport is a http.RoundTripper that connects to Unix domain sockets.
    91  type socketTransport struct {
    92  	DialTimeout           time.Duration
    93  	RequestTimeout        time.Duration
    94  	ResponseHeaderTimeout time.Duration
    95  	Socket                string
    96  }
    97  
    98  // RoundTrip executes a single HTTP transaction. See net/http.RoundTripper.
    99  func (t *socketTransport) RoundTrip(req *http.Request) (*http.Response, error) {
   100  	if req.URL == nil {
   101  		return nil, errors.New("http+unix: nil Request.URL")
   102  	}
   103  	if req.URL.Scheme != `http+unix` {
   104  		return nil, errors.New("unsupported protocol scheme: " + req.URL.Scheme)
   105  	}
   106  	if req.URL.Host == "" {
   107  		return nil, errors.New("http+unix: no Host in request URL")
   108  	}
   109  
   110  	c, err := net.DialTimeout("unix", t.Socket, t.DialTimeout)
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	r := bufio.NewReader(c)
   115  	if t.RequestTimeout > 0 {
   116  		c.SetWriteDeadline(time.Now().Add(t.RequestTimeout))
   117  	}
   118  	if err := req.Write(c); err != nil {
   119  		return nil, err
   120  	}
   121  	if t.ResponseHeaderTimeout > 0 {
   122  		c.SetReadDeadline(time.Now().Add(t.ResponseHeaderTimeout))
   123  	}
   124  	resp, err := http.ReadResponse(r, req)
   125  	return resp, err
   126  }