| 150 | } |
| 151 | |
| 152 | func getURL(ctx context.Context, urlStr string) error { |
| 153 | if urlStr == "login" { |
| 154 | urlStr = "https://login.tailscale.com" |
| 155 | } |
| 156 | log.SetOutput(os.Stdout) |
| 157 | ctx = httptrace.WithClientTrace(ctx, &httptrace.ClientTrace{ |
| 158 | GetConn: func(hostPort string) { log.Printf("GetConn(%q)", hostPort) }, |
| 159 | GotConn: func(info httptrace.GotConnInfo) { log.Printf("GotConn: %+v", info) }, |
| 160 | DNSStart: func(info httptrace.DNSStartInfo) { log.Printf("DNSStart: %+v", info) }, |
| 161 | DNSDone: func(info httptrace.DNSDoneInfo) { log.Printf("DNSDoneInfo: %+v", info) }, |
| 162 | TLSHandshakeStart: func() { log.Printf("TLSHandshakeStart") }, |
| 163 | TLSHandshakeDone: func(cs tls.ConnectionState, err error) { log.Printf("TLSHandshakeDone: %+v, %v", cs, err) }, |
| 164 | WroteRequest: func(info httptrace.WroteRequestInfo) { log.Printf("WroteRequest: %+v", info) }, |
| 165 | }) |
| 166 | req, err := http.NewRequestWithContext(ctx, "GET", urlStr, nil) |
| 167 | if err != nil { |
| 168 | return fmt.Errorf("http.NewRequestWithContext: %v", err) |
| 169 | } |
| 170 | var proxyURL *url.URL |
| 171 | if buildfeatures.HasUseProxy { |
| 172 | if proxyFromEnv, ok := feature.HookProxyFromEnvironment.GetOk(); ok { |
| 173 | proxyURL, err = proxyFromEnv(req) |
| 174 | if err != nil { |
| 175 | return fmt.Errorf("tshttpproxy.ProxyFromEnvironment: %v", err) |
| 176 | } |
| 177 | } |
| 178 | } |
| 179 | log.Printf("proxy: %v", proxyURL) |
| 180 | tr := &http.Transport{ |
| 181 | Proxy: func(*http.Request) (*url.URL, error) { return proxyURL, nil }, |
| 182 | ProxyConnectHeader: http.Header{}, |
| 183 | DisableKeepAlives: true, |
| 184 | } |
| 185 | if proxyURL != nil { |
| 186 | var auth string |
| 187 | if f, ok := feature.HookProxyGetAuthHeader.GetOk(); ok { |
| 188 | auth, err = f(proxyURL) |
| 189 | } |
| 190 | if err == nil && auth != "" { |
| 191 | tr.ProxyConnectHeader.Set("Proxy-Authorization", auth) |
| 192 | } |
| 193 | log.Printf("tshttpproxy.GetAuthHeader(%v) got: auth of %d bytes, err=%v", proxyURL, len(auth), err) |
| 194 | const truncLen = 20 |
| 195 | if len(auth) > truncLen { |
| 196 | auth = fmt.Sprintf("%s...(%d total bytes)", auth[:truncLen], len(auth)) |
| 197 | } |
| 198 | if auth != "" { |
| 199 | // We used log.Printf above (for timestamps). |
| 200 | // Use fmt.Printf here instead just to appease |
| 201 | // a security scanner, despite log.Printf only |
| 202 | // going to stdout. |
| 203 | fmt.Printf("... Proxy-Authorization = %q\n", auth) |
| 204 | } |
| 205 | } |
| 206 | res, err := tr.RoundTrip(req) |
| 207 | if err != nil { |
| 208 | return fmt.Errorf("Transport.RoundTrip: %v", err) |
| 209 | } |