1
Description: net/http: non-keepalive connections close successfully
2
Connections did not close if Request.Close or Response.Close was true. This
3
meant that if the user wanted the connection to close, or if the server
4
requested it via "Connection: close", the connection would not be closed.
5
Author: James Gray <james@james4k.com>
6
Bug-Debian: http://bugs.debian.org/683421
7
Origin: upstream, http://code.google.com/p/go/source/detail?r=820ffde8c396
9
Last-Update: 2012-08-01
13
--- golang-1.0.2.orig/src/pkg/net/http/transport.go
14
+++ golang-1.0.2/src/pkg/net/http/transport.go
15
@@ -603,6 +603,10 @@ func (pc *persistConn) readLoop() {
16
// before we race and peek on the underlying bufio reader.
17
if waitForBodyRead != nil {
20
+ // If waitForBodyRead is nil, and we're not alive, we
21
+ // must close the connection before we leave the loop.
26
--- golang-1.0.2.orig/src/pkg/net/http/transport_test.go
27
+++ golang-1.0.2/src/pkg/net/http/transport_test.go
28
@@ -13,6 +13,7 @@ import (
36
@@ -20,6 +21,7 @@ import (
44
@@ -35,6 +37,64 @@ var hostPortHandler = HandlerFunc(func(w
45
w.Write([]byte(r.RemoteAddr))
48
+type testCloseConn struct {
53
+func (conn *testCloseConn) Close() error {
54
+ conn.set.remove(conn)
55
+ return conn.Conn.Close()
58
+type testConnSet struct {
59
+ set map[net.Conn]bool
63
+func (tcs *testConnSet) insert(c net.Conn) {
65
+ defer tcs.mutex.Unlock()
69
+func (tcs *testConnSet) remove(c net.Conn) {
71
+ defer tcs.mutex.Unlock()
72
+ // just change to false, so we have a full set of opened connections
76
+// some tests use this to manage raw tcp connections for later inspection
77
+func makeTestDial() (*testConnSet, func(n, addr string) (net.Conn, error)) {
78
+ connSet := &testConnSet{
79
+ set: make(map[net.Conn]bool),
81
+ dial := func(n, addr string) (net.Conn, error) {
82
+ c, err := net.Dial(n, addr)
86
+ tc := &testCloseConn{c, connSet}
90
+ return connSet, dial
93
+func (tcs *testConnSet) countClosed() (closed, total int) {
95
+ defer tcs.mutex.Unlock()
97
+ total = len(tcs.set)
98
+ for _, open := range tcs.set {
106
// Two subsequent requests and verify their response is the same.
107
// The response from the server is our own IP:port
108
func TestTransportKeepAlives(t *testing.T) {
109
@@ -72,8 +132,12 @@ func TestTransportConnectionCloseOnRespo
110
ts := httptest.NewServer(hostPortHandler)
113
+ connSet, testDial := makeTestDial()
115
for _, connectionClose := range []bool{false, true} {
120
c := &Client{Transport: tr}
122
fetch := func(n int) string {
123
@@ -107,6 +171,13 @@ func TestTransportConnectionCloseOnRespo
124
t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
125
connectionClose, bodiesDiffer, body1, body2)
128
+ tr.CloseIdleConnections()
131
+ closed, total := connSet.countClosed()
132
+ if closed < total {
133
+ t.Errorf("%d out of %d tcp connections were not closed", total-closed, total)
137
@@ -114,8 +185,12 @@ func TestTransportConnectionCloseOnReque
138
ts := httptest.NewServer(hostPortHandler)
141
+ connSet, testDial := makeTestDial()
143
for _, connectionClose := range []bool{false, true} {
148
c := &Client{Transport: tr}
150
fetch := func(n int) string {
151
@@ -149,6 +224,13 @@ func TestTransportConnectionCloseOnReque
152
t.Errorf("error in connectionClose=%v. unexpected bodiesDiffer=%v; body1=%q; body2=%q",
153
connectionClose, bodiesDiffer, body1, body2)
156
+ tr.CloseIdleConnections()
159
+ closed, total := connSet.countClosed()
160
+ if closed < total {
161
+ t.Errorf("%d out of %d tcp connections were not closed", total-closed, total)