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 }