Skip to content

Commit c71304b

Browse files
committed
*: drop goproxy dependency
Assuming go-git is a library and so it's better to use minimal dependencies. github.com/elazarl/goproxy is only used by tests, adding a tiny implementation enables us to drop it. Signed-off-by: ferhat elmas <elmas.ferhat@gmail.com>
1 parent e83cbb9 commit c71304b

File tree

3 files changed

+102
-35
lines changed

3 files changed

+102
-35
lines changed

go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ require (
77
github.com/Microsoft/go-winio v0.6.2
88
github.com/ProtonMail/go-crypto v1.3.0
99
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
10-
github.com/elazarl/goproxy v1.7.2
1110
github.com/emirpasic/gods v1.18.1
1211
github.com/gliderlabs/ssh v0.3.8
1312
github.com/go-git/gcfg/v2 v2.0.2

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1
1414
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1515
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1616
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
17-
github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o=
18-
github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE=
1917
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
2018
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
2119
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=

plumbing/transport/http/proxy_test.go

Lines changed: 102 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"sync/atomic"
1414
"testing"
1515

16-
"github.com/elazarl/goproxy"
1716
fixtures "github.com/go-git/go-git-fixtures/v5"
1817
"github.com/stretchr/testify/assert"
1918
"github.com/stretchr/testify/require"
@@ -39,9 +38,7 @@ type ProxySuite struct {
3938
func (s *ProxySuite) TestAdvertisedReferencesHTTP() {
4039
var proxiedRequests int32
4140

42-
proxy := goproxy.NewProxyHttpServer()
43-
44-
setupHTTPProxy(proxy, &proxiedRequests)
41+
proxy := newTestProxy(&proxiedRequests)
4542

4643
httpProxyAddr := setupProxyServer(s.T(), proxy, false, true)
4744

@@ -76,8 +73,7 @@ func (s *ProxySuite) TestAdvertisedReferencesHTTP() {
7673
func (s *ProxySuite) TestAdvertisedReferencesHTTPS() {
7774
var proxiedRequests int32
7875

79-
proxy := goproxy.NewProxyHttpServer()
80-
setupHTTPSProxy(proxy, &proxiedRequests)
76+
proxy := newTestProxy(&proxiedRequests)
8177

8278
httpsProxyAddr := setupProxyServer(s.T(), proxy, true, true)
8379

@@ -179,37 +175,111 @@ func setupProxyServer(t testing.TB, handler http.Handler, isTLS, schemaAddr bool
179175
return httpProxyAddr
180176
}
181177

182-
func setupHTTPProxy(proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) {
183-
// The request is being forwarded to the local test git server in this handler.
184-
var proxyHandler goproxy.FuncReqHandler = func(req *http.Request, _ *goproxy.ProxyCtx) (*http.Request, *http.Response) {
185-
if strings.Contains(req.Host, "localhost") {
186-
user, pass, _ := parseBasicAuth(req.Header.Get("Proxy-Authorization"))
187-
if user != "user" || pass != "pass" {
188-
return req, goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusUnauthorized, "")
189-
}
190-
atomic.AddInt32(proxiedRequests, 1)
191-
return req, nil
192-
}
193-
// Reject if it isn't our request.
194-
return req, goproxy.NewResponse(req, goproxy.ContentTypeText, http.StatusForbidden, "")
178+
// testProxy is a minimal HTTP/HTTPS proxy for testing.
179+
type testProxy struct {
180+
proxiedRequests *int32
181+
}
182+
183+
func newTestProxy(proxiedRequests *int32) *testProxy {
184+
return &testProxy{proxiedRequests: proxiedRequests}
185+
}
186+
187+
func (p *testProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
188+
// Check proxy authentication
189+
user, pass, _ := parseBasicAuth(r.Header.Get("Proxy-Authorization"))
190+
if user != "user" || pass != "pass" {
191+
http.Error(w, "Proxy Authentication Required", http.StatusProxyAuthRequired)
192+
return
193+
}
194+
195+
if r.Method == http.MethodConnect {
196+
// HTTPS proxy: handle CONNECT requests
197+
p.handleConnect(w, r)
198+
} else {
199+
// HTTP proxy: forward the request
200+
p.handleHTTP(w, r)
195201
}
196-
proxy.OnRequest().Do(proxyHandler)
197202
}
198203

199-
func setupHTTPSProxy(proxy *goproxy.ProxyHttpServer, proxiedRequests *int32) {
200-
var proxyHandler goproxy.FuncHttpsHandler = func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
201-
if strings.Contains(host, "github.com") {
202-
user, pass, _ := parseBasicAuth(ctx.Req.Header.Get("Proxy-Authorization"))
203-
if user != "user" || pass != "pass" {
204-
return goproxy.RejectConnect, host
205-
}
206-
atomic.AddInt32(proxiedRequests, 1)
207-
return goproxy.OkConnect, host
204+
func (p *testProxy) handleConnect(w http.ResponseWriter, r *http.Request) {
205+
// Only allow connections to github.com for HTTPS tests
206+
if !strings.Contains(r.Host, "github.com") && !strings.Contains(r.Host, "localhost") {
207+
http.Error(w, "Forbidden", http.StatusForbidden)
208+
return
209+
}
210+
211+
atomic.AddInt32(p.proxiedRequests, 1)
212+
213+
// Establish connection to the target
214+
targetConn, err := net.Dial("tcp", r.Host)
215+
if err != nil {
216+
http.Error(w, err.Error(), http.StatusServiceUnavailable)
217+
return
218+
}
219+
220+
// Send 200 Connection Established
221+
w.WriteHeader(http.StatusOK)
222+
223+
// Hijack the connection
224+
hijacker, ok := w.(http.Hijacker)
225+
if !ok {
226+
http.Error(w, "Hijacking not supported", http.StatusInternalServerError)
227+
targetConn.Close()
228+
return
229+
}
230+
231+
clientConn, _, err := hijacker.Hijack()
232+
if err != nil {
233+
http.Error(w, err.Error(), http.StatusServiceUnavailable)
234+
targetConn.Close()
235+
return
236+
}
237+
238+
// Tunnel data between client and target
239+
go func() {
240+
defer targetConn.Close()
241+
defer clientConn.Close()
242+
io.Copy(targetConn, clientConn)
243+
}()
244+
go func() {
245+
defer targetConn.Close()
246+
defer clientConn.Close()
247+
io.Copy(clientConn, targetConn)
248+
}()
249+
}
250+
251+
func (p *testProxy) handleHTTP(w http.ResponseWriter, r *http.Request) {
252+
// Only allow requests to localhost for HTTP tests
253+
if !strings.Contains(r.Host, "localhost") {
254+
http.Error(w, "Forbidden", http.StatusForbidden)
255+
return
256+
}
257+
258+
atomic.AddInt32(p.proxiedRequests, 1)
259+
260+
// Create a new request to the target
261+
outReq := r.Clone(r.Context())
262+
outReq.RequestURI = ""
263+
264+
// Remove hop-by-hop headers
265+
outReq.Header.Del("Proxy-Connection")
266+
outReq.Header.Del("Proxy-Authorization")
267+
268+
resp, err := http.DefaultTransport.RoundTrip(outReq)
269+
if err != nil {
270+
http.Error(w, err.Error(), http.StatusBadGateway)
271+
return
272+
}
273+
defer resp.Body.Close()
274+
275+
// Copy response headers
276+
for key, values := range resp.Header {
277+
for _, value := range values {
278+
w.Header().Add(key, value)
208279
}
209-
// Reject if it isn't our request.
210-
return goproxy.RejectConnect, host
211280
}
212-
proxy.OnRequest().HandleConnect(proxyHandler)
281+
w.WriteHeader(resp.StatusCode)
282+
io.Copy(w, resp.Body)
213283
}
214284

215285
// adapted from https://github.com/golang/go/blob/2ef70d9d0f98832c8103a7968b195e560a8bb262/src/net/http/request.go#L959

0 commit comments

Comments
 (0)