@@ -886,19 +886,33 @@ type data struct {
886886// should return the "internal" server and not "masked" server.
887887func TestChangeResponseHeader (t * testing.T ) {
888888 t .Parallel ()
889- proxyPort := uint16 (30092 )
890- internalPort := uint64 (30090 )
891- maskedPort := uint16 (30091 )
892889
893- client := & http. Client {}
890+ var lisCfg net. ListenConfig
894891
895- proxyURL , err := url .Parse (fmt .Sprintf ("http://127.0.0.1:%d" , proxyPort ))
892+ // Pre-listen on ephemeral ports so we know the servers are accepting
893+ // connections before the test starts firing requests, and to avoid
894+ // hardcoded-port collisions between parallel test runs.
895+ internalListener , err := lisCfg .Listen (t .Context (), "tcp" , "127.0.0.1:0" )
896896 require .NoError (t , err )
897- maskedHost := fmt .Sprintf ("127.0.0.1:%d" , maskedPort )
898- internalURL , err := url .Parse (fmt .Sprintf ("http://127.0.0.1:%d" , internalPort ))
897+ internalAddr := internalListener .Addr ().(* net.TCPAddr )
898+ internalPort := uint64 (internalAddr .Port ) //nolint:gosec // test-only port number always fits
899+ internalURL , err := url .Parse (fmt .Sprintf ("http://%s" , internalAddr .String ()))
899900 require .NoError (t , err )
900901
901- // start proxy
902+ maskedListener , err := lisCfg .Listen (t .Context (), "tcp" , "127.0.0.1:0" )
903+ require .NoError (t , err )
904+ maskedAddr := maskedListener .Addr ().(* net.TCPAddr )
905+ maskedHost := maskedAddr .String ()
906+
907+ proxyListener , err := lisCfg .Listen (t .Context (), "tcp" , "127.0.0.1:0" )
908+ require .NoError (t , err )
909+ proxyAddr := proxyListener .Addr ().(* net.TCPAddr )
910+ proxyPort := uint16 (proxyAddr .Port ) //nolint:gosec // test-only port number always fits
911+ proxyURL , err := url .Parse (fmt .Sprintf ("http://%s" , proxyAddr .String ()))
912+ require .NoError (t , err )
913+
914+ client := & http.Client {}
915+
902916 proxy := New (proxyPort , 1 , time .Second , func (_ * http.Request ) (* pool.Destination , error ) {
903917 return & pool.Destination {
904918 Url : internalURL ,
@@ -913,7 +927,7 @@ func TestChangeResponseHeader(t *testing.T) {
913927 }, nil , false )
914928
915929 go func () {
916- err = proxy .ListenAndServe ( t . Context () )
930+ err : = proxy .Serve ( proxyListener )
917931 assert .ErrorIs (t , err , http .ErrServerClosed )
918932 }()
919933
@@ -922,54 +936,57 @@ func TestChangeResponseHeader(t *testing.T) {
922936 assert .NoError (t , err )
923937 })
924938
925- // start internal server
926- internalServer := http.Server {
927- Addr : fmt .Sprintf ("127.0.0.1:%d" , internalPort ),
939+ internalServer := & http.Server {
928940 Handler : http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
929941 w .WriteHeader (http .StatusOK )
930- err = json .NewEncoder (w ).Encode (data {"internal" , r .Host , r .Header })
931- assert .NoError (t , err )
942+ encErr : = json .NewEncoder (w ).Encode (data {"internal" , r .Host , r .Header })
943+ assert .NoError (t , encErr )
932944 }),
933945 }
934946 go func () {
935- err = internalServer .ListenAndServe ( )
936- assert .NoError (t , err )
947+ serveErr : = internalServer .Serve ( internalListener )
948+ assert .ErrorIs (t , serveErr , http . ErrServerClosed )
937949 }()
950+ t .Cleanup (func () {
951+ assert .NoError (t , internalServer .Close ())
952+ })
938953
939- // start fake server
940- maskedServer := http.Server {
941- Addr : fmt .Sprintf ("127.0.0.1:%d" , maskedPort ),
954+ maskedServer := & http.Server {
942955 Handler : http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
943956 w .WriteHeader (http .StatusOK )
944- err = json .NewEncoder (w ).Encode (data {"masked" , r .Host , r .Header })
945- assert .NoError (t , err )
957+ encErr : = json .NewEncoder (w ).Encode (data {"masked" , r .Host , r .Header })
958+ assert .NoError (t , encErr )
946959 }),
947960 }
948961 go func () {
949- err = maskedServer .ListenAndServe ( )
950- assert .NoError (t , err )
962+ serveErr : = maskedServer .Serve ( maskedListener )
963+ assert .ErrorIs (t , serveErr , http . ErrServerClosed )
951964 }()
965+ t .Cleanup (func () {
966+ assert .NoError (t , maskedServer .Close ())
967+ })
952968
953- // create request
954969 req , err := http .NewRequestWithContext (t .Context (), http .MethodGet , proxyURL .String (), nil )
955- req .Header .Set ("Host" , fmt .Sprintf ("localhost:%d" , proxyPort ))
956- req .Header .Set ("e2b-testing" , "test123" )
957970 require .NoError (t , err )
971+ req .Host = fmt .Sprintf ("localhost:%d" , proxyPort )
972+ req .Header .Set ("e2b-testing" , "test123" )
958973
974+ // Retry while the proxy goroutine is still binding to the port. Once the
975+ // proxy is up, the internal server is guaranteed listening (we pre-bound
976+ // its listener above), so we don't need to retry on bad status.
959977 var rsp * http.Response
960- for range 10 {
978+ for range 50 {
961979 rsp , err = client .Do (req )
962980 if err == nil {
963981 t .Cleanup (func () {
964- err = rsp .Body .Close ()
965- assert .NoError (t , err )
982+ assert .NoError (t , rsp .Body .Close ())
966983 })
967984
968985 break
969986 }
970987
971988 if errors .Is (err , syscall .ECONNREFUSED ) {
972- time .Sleep (100 * time .Millisecond )
989+ time .Sleep (20 * time .Millisecond )
973990
974991 continue
975992 }
@@ -987,9 +1004,9 @@ func TestChangeResponseHeader(t *testing.T) {
9871004 require .NoError (t , err )
9881005
9891006 assert .Equal (t , "internal" , data .Tag )
990- assert .Equal (t , fmt . Sprintf ( "127.0.0.1:%d" , maskedPort ) , data .Host )
1007+ assert .Equal (t , maskedHost , data .Host )
9911008 assert .Equal (t , "test123" , data .Headers .Get ("E2b-Testing" ))
992- assert .Equal (t , fmt .Sprintf ("127.0.0.1 :%d" , proxyPort ), data .Headers .Get ("X-Forwarded-Host" ))
1009+ assert .Equal (t , fmt .Sprintf ("localhost :%d" , proxyPort ), data .Headers .Get ("X-Forwarded-Host" ))
9931010}
9941011
9951012func TestConnectionLimitBlocksExcessConnections (t * testing.T ) {
0 commit comments