Skip to content

Commit 13e53bc

Browse files
Add ProxyConnectError type to be returned on non 200 responses to HTTP CONNECT requests
1 parent 8869086 commit 13e53bc

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/net/http/transport.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,6 +1553,19 @@ type erringRoundTripper interface {
15531553
RoundTripErr() error
15541554
}
15551555

1556+
type ProxyConnectError struct {
1557+
Response *Response
1558+
}
1559+
1560+
func (p *ProxyConnectError) Error() string {
1561+
// Don't return full Response.Status for backwards compatibility
1562+
f := strings.SplitN(p.Response.Status, " ", 2)
1563+
if len(f) < 2 {
1564+
return "unknown status code"
1565+
}
1566+
return f[1]
1567+
}
1568+
15561569
func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *persistConn, err error) {
15571570
pconn = &persistConn{
15581571
t: t,
@@ -1711,12 +1724,10 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
17111724
return nil, err
17121725
}
17131726
if resp.StatusCode != 200 {
1714-
f := strings.SplitN(resp.Status, " ", 2)
17151727
conn.Close()
1716-
if len(f) < 2 {
1717-
return nil, errors.New("unknown status code")
1728+
return nil, &ProxyConnectError{
1729+
Response: resp,
17181730
}
1719-
return nil, errors.New(f[1])
17201731
}
17211732
}
17221733

src/net/http/transport_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,6 +3774,41 @@ func TestRoundTripReturnsProxyError(t *testing.T) {
37743774
}
37753775
}
37763776

3777+
// Test for issue 38143
3778+
// Return an error containing the proxy CONNECT request if status is not 200
3779+
func TestRoundTripReturnsProxyConnectError(t *testing.T) {
3780+
s := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
3781+
w.WriteHeader(StatusServiceUnavailable)
3782+
}))
3783+
defer s.Close()
3784+
3785+
proxyURL, err := url.Parse(s.URL)
3786+
if err != nil {
3787+
t.Fatal(err)
3788+
}
3789+
tr := &Transport{
3790+
Proxy: ProxyURL(proxyURL),
3791+
}
3792+
3793+
req, err := NewRequest("GET", "https://example.com", nil)
3794+
if err != nil {
3795+
t.Fatal(err)
3796+
}
3797+
3798+
_, got := tr.RoundTrip(req)
3799+
3800+
switch errType := got.(type) {
3801+
case *ProxyConnectError:
3802+
default:
3803+
t.Errorf("Wrong error type returned, Got: %T, Want: *ProxyConnectError", errType)
3804+
}
3805+
3806+
// Test backwards compatibility
3807+
if got.Error() != "Service Unavailable" {
3808+
t.Error("Non-backwards compatible error message from *ProxyConnectError")
3809+
}
3810+
}
3811+
37773812
// tests that putting an idle conn after a call to CloseIdleConns does return it
37783813
func TestTransportCloseIdleConnsThenReturn(t *testing.T) {
37793814
tr := &Transport{}

0 commit comments

Comments
 (0)