@@ -722,7 +722,7 @@ func TestHttpProxyAddrsFromEnv(t *testing.T) {
722722 os .Setenv ("http_proxy" , l .URL )
723723 os .Setenv ("https_proxy" , l .URL )
724724 proxy2 := goproxy .NewProxyHttpServer ()
725-
725+
726726 client , l2 := oneShotProxy (proxy2 , t )
727727 defer l2 .Close ()
728728 if r := string (getOrFail (https .URL + "/bobo" , client , t )); r != "bobo bobo" {
@@ -733,6 +733,90 @@ func TestHttpProxyAddrsFromEnv(t *testing.T) {
733733 os .Unsetenv ("https_proxy" )
734734}
735735
736+ func TestOverrideHttpsProxyAddrsFromEnvWithRequest (t * testing.T ) {
737+ // The request essentially does:
738+ // Client -> FakeStripeEgressProxy -> FakeExternalProxy -> FinalDestination
739+ finalDestinationUrl := "https://httpbin.org/get"
740+
741+ // We'll use this counter to mark whether FakeStripeEgressProxy has been called
742+ c := 0
743+
744+ // TODO(pspieker): figure out why this doesn't work - for now, this is fine,
745+ // but we should fix this in the medium term before a wider launch
746+ //
747+ // We should set the env vars here to ensure that our per-request config overrides these
748+ // os.Setenv("http_proxy", "http://incorrectproxy.com")
749+ // os.Setenv("https_proxy", "http://incorrectproxy.com")
750+
751+ fakeExternalProxy := goproxy .NewProxyHttpServer ()
752+ fakeExternalProxyTestStruct := httptest .NewServer (fakeExternalProxy )
753+ fakeExternalProxy .OnRequest ().HandleConnect (goproxy .AlwaysMitm )
754+ tagExternalProxyPassthrough := func (resp * http.Response , ctx * goproxy.ProxyCtx ) * http.Response {
755+ b , err := ioutil .ReadAll (resp .Body )
756+ panicOnErr (err , "readAll resp" )
757+ resp .Body = ioutil .NopCloser (bytes .NewBufferString (string (b ) + "-externalproxy" ))
758+ return resp
759+ }
760+ fakeExternalProxy .OnResponse ().DoFunc (tagExternalProxyPassthrough )
761+
762+ fakeStripeEgressProxy := goproxy .NewProxyHttpServer ()
763+ // We set the CONNECT response handler function to increment our counter such that we can tell
764+ // if our FakeStripeEgressProxy was actually called
765+ fakeStripeEgressProxy .ConnectRespHandler = func (ctx * goproxy.ProxyCtx , resp * http.Response ) error {
766+ c += 1
767+ return nil
768+ }
769+ fakeStripeEgressProxyTestStruct := httptest .NewServer (fakeStripeEgressProxy )
770+
771+ // Next, we construct the client that we'll be using to talk to our 2 proxies
772+ egressProxyUrl , _ := url .Parse (fakeStripeEgressProxyTestStruct .URL )
773+ tr := & http.Transport {
774+ TLSClientConfig : acceptAllCerts ,
775+ Proxy : http .ProxyURL (egressProxyUrl ),
776+ ProxyConnectHeader : map [string ][]string {
777+ goproxy .PerRequestHTTPSProxyHeaderKey : {fakeExternalProxyTestStruct .URL },
778+ },
779+ }
780+ client := & http.Client {Transport : tr }
781+
782+ req , err := http .NewRequest ("GET" , finalDestinationUrl , nil )
783+ if err != nil {
784+ t .Fatal ("Unable to construct request!" )
785+ }
786+
787+ req .Header .Set ("X-Test-Header-Key" , "Test-Header-Value" )
788+
789+ res , err := client .Do (req )
790+ if err != nil {
791+ t .Fatal ("Unable to make the request!" )
792+ }
793+
794+ bodyBytes , err := io .ReadAll (res .Body )
795+ if err != nil {
796+ t .Fatal ("Unable to parse the response bytes!" )
797+ }
798+ resBody := string (bodyBytes )
799+
800+ // Making sure we received the response we expected from the final destination
801+ if ! strings .Contains (resBody , "\" X-Test-Header-Key\" : \" Test-Header-Value\" " ) {
802+ t .Error ("Expected the passed request headers to be present in the response body!" )
803+ }
804+
805+ // Ensuring the external proxy was routed through
806+ if ! strings .Contains (resBody , "-externalproxy" ) {
807+ t .Error ("Expected the request have been passed through the external proxy on the way to the final destination!" )
808+ }
809+
810+ // Ensuring the "internal" egress proxy was routed through
811+ if c != 1 {
812+ t .Error ("Expected the internal egress proxy to have been passed through!" )
813+ }
814+
815+ // TODO(pspieker): see comment above
816+ // os.Unsetenv("http_proxy")
817+ // os.Unsetenv("https_proxy")
818+ }
819+
736820func TestCustomHttpProxyAddrs (t * testing.T ) {
737821 proxy := goproxy .NewProxyHttpServer ()
738822 doubleString := func (resp * http.Response , ctx * goproxy.ProxyCtx ) * http.Response {
@@ -748,7 +832,7 @@ func TestCustomHttpProxyAddrs(t *testing.T) {
748832 defer l .Close ()
749833
750834 proxy2 := goproxy .NewProxyHttpServer (goproxy .WithHttpProxyAddr (l .URL ), goproxy .WithHttpsProxyAddr (l .URL ))
751-
835+
752836 client , l2 := oneShotProxy (proxy2 , t )
753837 defer l2 .Close ()
754838 if r := string (getOrFail (https .URL + "/bobo" , client , t )); r != "bobo bobo" {
0 commit comments