@@ -1122,6 +1122,45 @@ func TestReverseProxy_PanicBodyError(t *testing.T) {
1122
1122
rproxy .ServeHTTP (httptest .NewRecorder (), req )
1123
1123
}
1124
1124
1125
+ // Issue #46866: panic without closing incoming request body causes a panic
1126
+ func TestReverseProxy_PanicClosesIncomingBody (t * testing.T ) {
1127
+ backend := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1128
+ out := "this call was relayed by the reverse proxy"
1129
+ // Coerce a wrong content length to induce io.ErrUnexpectedEOF
1130
+ w .Header ().Set ("Content-Length" , fmt .Sprintf ("%d" , len (out )* 2 ))
1131
+ fmt .Fprintln (w , out )
1132
+ }))
1133
+ defer backend .Close ()
1134
+ backendURL , err := url .Parse (backend .URL )
1135
+ if err != nil {
1136
+ t .Fatal (err )
1137
+ }
1138
+ proxyHandler := NewSingleHostReverseProxy (backendURL )
1139
+ proxyHandler .ErrorLog = log .New (ioutil .Discard , "" , 0 ) // quiet for tests
1140
+ frontend := httptest .NewServer (proxyHandler )
1141
+ defer frontend .Close ()
1142
+ frontendClient := frontend .Client ()
1143
+
1144
+ var wg sync.WaitGroup
1145
+ for i := 0 ; i < 2 ; i ++ {
1146
+ wg .Add (1 )
1147
+ go func () {
1148
+ defer wg .Done ()
1149
+ for j := 0 ; j < 10 ; j ++ {
1150
+ const reqLen = 6 * 1024 * 1024
1151
+ req , _ := http .NewRequest ("POST" , frontend .URL , & io.LimitedReader {R : neverEnding ('x' ), N : reqLen })
1152
+ req .ContentLength = reqLen
1153
+ resp , _ := frontendClient .Transport .RoundTrip (req )
1154
+ if resp != nil {
1155
+ io .Copy (ioutil .Discard , resp .Body )
1156
+ resp .Body .Close ()
1157
+ }
1158
+ }
1159
+ }()
1160
+ }
1161
+ wg .Wait ()
1162
+ }
1163
+
1125
1164
func TestSelectFlushInterval (t * testing.T ) {
1126
1165
tests := []struct {
1127
1166
name string
0 commit comments