feature: Add support for HTTP_PROXY, HTTPS_PROXY, and NO_PROXY#1260
feature: Add support for HTTP_PROXY, HTTPS_PROXY, and NO_PROXY#1260
Conversation
keegancsmith
left a comment
There was a problem hiding this comment.
Nice! Inline comments, but otherwise LGTM
internal/api/api.go
Outdated
| if opts.ProxyURL != nil || opts.ProxyPath != "" { | ||
| // Explicit SRC_PROXY configuration takes precedence. | ||
| transport = withProxyTransport(transport, opts.ProxyURL, opts.ProxyPath) | ||
| } else if proxyURL := envProxyURL(opts.Endpoint); proxyURL != nil && proxyURL.Scheme == "https" { |
There was a problem hiding this comment.
why does https:// not work without intervention? (as documented below for http and socks5)
There was a problem hiding this comment.
Since we're connecting to the SG API using HTTP/2, the standard transport tries to connect to the TLS-enabled proxy using HTTP/2 also, which fails if the proxy doesn't support HTTP/2. I haven't found a proxy for local testing that does support HTTP/2; I suspect that most/all proxies that are TLS-enabled don't support HTTP/2.
internal/api/proxy_test.go
Outdated
| ln, err := net.Listen("tcp", "127.0.0.1:0") | ||
| if err != nil { | ||
| t.Fatalf("proxy listen: %v", err) | ||
| } | ||
|
|
||
| srv := &http.Server{Handler: handler} | ||
|
|
||
| if useTLS { | ||
| cert := generateTestCert(t, "127.0.0.1") | ||
| srv.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}} | ||
| go srv.ServeTLS(ln, "", "") | ||
| } else { | ||
| go srv.Serve(ln) | ||
| } | ||
| t.Cleanup(func() { srv.Close() }) | ||
|
|
||
| // Wait for the server to be ready | ||
| waitForServerReady(t, ln.Addr().String(), useTLS, 5*time.Second) | ||
|
|
||
| scheme := "http" | ||
| if useTLS { | ||
| scheme = "https" | ||
| } | ||
| pURL, _ := url.Parse(fmt.Sprintf("%s://%s", scheme, ln.Addr().String())) | ||
| return pURL, ch |
There was a problem hiding this comment.
I think you can greatly simplify code here (and remove helpers like waitForServerReady and generateTestCert) by using the httptest package. It already provides functions to listen on TLS/etc and does things like wait for the server to be listening.
There was a problem hiding this comment.
I think I finally fixed up these tests?
|
You might wanna rebase, I think william just did some CI updates which include things like go-lint/etc. |
|
Thanks for all of your commentary; I forgot to open this PR in draft mode! Been trying to address what looks like flakey tests in the Ubuntu CI runner; I'll go through your very helpful comments soon. |
|
This change is part of the following stack: Change managed by git-spice. |
b1d6176 to
05f0fbb
Compare
|
@peterguy alright just re-request review when ready. |
622bd60 to
3536377
Compare
keegancsmith
left a comment
There was a problem hiding this comment.
Requesting changes since I just wanna re-review once you have addressed the comments. FYI I pushed some commits to resolve the CI issues.
internal/api/proxy_test.go
Outdated
| ln, err := net.Listen("tcp", "127.0.0.1:0") | ||
| if err != nil { | ||
| t.Fatalf("proxy listen: %v", err) | ||
| } | ||
|
|
||
| srv := &http.Server{Handler: handler} | ||
|
|
||
| if useTLS { | ||
| cert := generateTestCert(t, "127.0.0.1") | ||
| srv.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}} | ||
| go srv.ServeTLS(ln, "", "") | ||
| } else { | ||
| go srv.Serve(ln) | ||
| } | ||
| t.Cleanup(func() { srv.Close() }) | ||
|
|
||
| // Wait for the server to be ready | ||
| waitForServerReady(t, ln.Addr().String(), useTLS, 5*time.Second) | ||
|
|
||
| scheme := "http" | ||
| if useTLS { | ||
| scheme = "https" | ||
| } | ||
| pURL, _ := url.Parse(fmt.Sprintf("%s://%s", scheme, ln.Addr().String())) | ||
| return pURL, ch |
|
I would wait for an update for Keegan's requested changes before doing my review pass if that's okay. |
6ab67e5 to
78eadd2
Compare
78eadd2 to
54aada1
Compare
cab95e8 to
97c1b0a
Compare
448305b to
a0d8f91
Compare
5ccd030 to
9ad25e5
Compare
a0d8f91 to
ed682d7
Compare
… env up front so that typos and malformed urls will surface immediately
…e proxy in the config is now the one gathered from either SRC_PROXY or the standard env variables
… that proxies are used
…tlsConn.Close()`) is necessary
…ng in the custom dialer
ed682d7 to
45a8725
Compare
|
Alright; I think this is cleaned up and ready for a re-review. |
|
Amp found two things, please take them with a grain of salt:
|
Adds support for the standard environment variables
HTTP_PROXY,HTTPS_PROXY, andNO_PROXY.SRC_PROXYstill takes precedence, including overNO_PROXY.Also added fixes for connecting to TLS-enabled proxies, where we want to connect to the SG API using HTTP/2, but many TLS-enabled proxies support only HTTP/1.1, so we need to connect to the proxy via HTTP/1.1, then connect through the proxy to the SG API using HTTP/2.
Moved endpoint and proxy parsing to the config building so that typos and malformed urls are caught early and errors returned immediately.
Test plan
Added CI tests validating proxy behavior.
Manual testing
Install
mitmproxyandsquid.Create an SSL cert for
squid:Create a config for
squid:Run mitmproxy -
mitmproxy -v- in one terminal.Run squid -
squid -f ./squid.conf -N -d 1- in another terminal.In a third terminal, in the src-cli repo, build the binary:
go build -o ./src-cli ./cmd/srcEnsure you have
SRC_ENDPOINTandSRC_ACCESS_TOKENset in your environment, and unsetSRC_PROXY.SRC_ENDPOINTneeds to behttps://.Try connecting with each proxy (
mitmproxyis 8080,squidis 8445) and with no proxy:You should get eleven "Authenticated as [USER] on [ENDPOINT]" messages in your terminal. You should see three connections in each of the
mitmproxyandsquidterminals. This ensures the program will read all of the proxy environment variables, ignoreHTTP_PROXY, will honorNO_PROXYwhenHTTPS_PROXYis defined, and ignoreNO_PROXYwhenSRC_PROXYis defined.This tests connecting through a proxy that connects with http (
mitmproxy), and one that is TLS-enabled (squid).Closes https://linear.app/sourcegraph/issue/CPL-236/src-cli-support-standard-http-proxy