@@ -1185,94 +1185,142 @@ func testTransportGzip(t *testing.T, mode testMode) {
1185
1185
}
1186
1186
}
1187
1187
1188
- // If a request has Expect:100-continue header, the request blocks sending body until the first response.
1189
- // Premature consumption of the request body should not be occurred.
1190
- func TestTransportExpect100Continue (t * testing.T ) {
1191
- run (t , testTransportExpect100Continue , []testMode {http1Mode })
1188
+ // A transport100Continue test exercises Transport behaviors when sending a
1189
+ // request with an Expect: 100-continue header.
1190
+ type transport100ContinueTest struct {
1191
+ t * testing.T
1192
+
1193
+ reqdone chan struct {}
1194
+ resp * Response
1195
+ respErr error
1196
+
1197
+ conn net.Conn
1198
+ reader * bufio.Reader
1192
1199
}
1193
- func testTransportExpect100Continue (t * testing.T , mode testMode ) {
1194
- ts := newClientServerTest (t , mode , HandlerFunc (func (rw ResponseWriter , req * Request ) {
1195
- switch req .URL .Path {
1196
- case "/100" :
1197
- // This endpoint implicitly responds 100 Continue and reads body.
1198
- if _ , err := io .Copy (io .Discard , req .Body ); err != nil {
1199
- t .Error ("Failed to read Body" , err )
1200
- }
1201
- rw .WriteHeader (StatusOK )
1202
- case "/200" :
1203
- // Go 1.5 adds Connection: close header if the client expect
1204
- // continue but not entire request body is consumed.
1205
- rw .WriteHeader (StatusOK )
1206
- case "/500" :
1207
- rw .WriteHeader (StatusInternalServerError )
1208
- case "/keepalive" :
1209
- // This hijacked endpoint responds error without Connection:close.
1210
- _ , bufrw , err := rw .(Hijacker ).Hijack ()
1211
- if err != nil {
1212
- log .Fatal (err )
1213
- }
1214
- bufrw .WriteString ("HTTP/1.1 500 Internal Server Error\r \n " )
1215
- bufrw .WriteString ("Content-Length: 0\r \n \r \n " )
1216
- bufrw .Flush ()
1217
- case "/timeout" :
1218
- // This endpoint tries to read body without 100 (Continue) response.
1219
- // After ExpectContinueTimeout, the reading will be started.
1220
- conn , bufrw , err := rw .(Hijacker ).Hijack ()
1221
- if err != nil {
1222
- log .Fatal (err )
1223
- }
1224
- if _ , err := io .CopyN (io .Discard , bufrw , req .ContentLength ); err != nil {
1225
- t .Error ("Failed to read Body" , err )
1226
- }
1227
- bufrw .WriteString ("HTTP/1.1 200 OK\r \n \r \n " )
1228
- bufrw .Flush ()
1229
- conn .Close ()
1230
- }
1231
1200
1232
- })). ts
1201
+ const transport100ContinueTestBody = "request body"
1233
1202
1234
- tests := []struct {
1235
- path string
1236
- body []byte
1237
- sent int
1238
- status int
1239
- }{
1240
- {path : "/100" , body : []byte ("hello" ), sent : 5 , status : 200 }, // Got 100 followed by 200, entire body is sent.
1241
- {path : "/200" , body : []byte ("hello" ), sent : 0 , status : 200 }, // Got 200 without 100. body isn't sent.
1242
- {path : "/500" , body : []byte ("hello" ), sent : 0 , status : 500 }, // Got 500 without 100. body isn't sent.
1243
- {path : "/keepalive" , body : []byte ("hello" ), sent : 0 , status : 500 }, // Although without Connection:close, body isn't sent.
1244
- {path : "/timeout" , body : []byte ("hello" ), sent : 5 , status : 200 }, // Timeout exceeded and entire body is sent.
1203
+ // newTransport100ContinueTest creates a Transport and sends an Expect: 100-continue
1204
+ // request on it.
1205
+ func newTransport100ContinueTest (t * testing.T , timeout time.Duration ) * transport100ContinueTest {
1206
+ ln := newLocalListener (t )
1207
+ defer ln .Close ()
1208
+
1209
+ test := & transport100ContinueTest {
1210
+ t : t ,
1211
+ reqdone : make (chan struct {}),
1245
1212
}
1246
1213
1247
- c := ts .Client ()
1248
- for i , v := range tests {
1249
- tr := & Transport {
1250
- ExpectContinueTimeout : 2 * time .Second ,
1251
- }
1252
- defer tr .CloseIdleConnections ()
1253
- c .Transport = tr
1254
- body := bytes .NewReader (v .body )
1255
- req , err := NewRequest ("PUT" , ts .URL + v .path , body )
1256
- if err != nil {
1257
- t .Fatal (err )
1258
- }
1214
+ tr := & Transport {
1215
+ ExpectContinueTimeout : timeout ,
1216
+ }
1217
+ go func () {
1218
+ defer close (test .reqdone )
1219
+ body := strings .NewReader (transport100ContinueTestBody )
1220
+ req , _ := NewRequest ("PUT" , "http://" + ln .Addr ().String (), body )
1259
1221
req .Header .Set ("Expect" , "100-continue" )
1260
- req .ContentLength = int64 (len (v .body ))
1222
+ req .ContentLength = int64 (len (transport100ContinueTestBody ))
1223
+ test .resp , test .respErr = tr .RoundTrip (req )
1224
+ test .resp .Body .Close ()
1225
+ }()
1261
1226
1262
- resp , err := c .Do (req )
1263
- if err != nil {
1264
- t .Fatal (err )
1227
+ c , err := ln .Accept ()
1228
+ if err != nil {
1229
+ t .Fatalf ("Accept: %v" , err )
1230
+ }
1231
+ t .Cleanup (func () {
1232
+ c .Close ()
1233
+ })
1234
+ br := bufio .NewReader (c )
1235
+ _ , err = ReadRequest (br )
1236
+ if err != nil {
1237
+ t .Fatalf ("ReadRequest: %v" , err )
1238
+ }
1239
+ test .conn = c
1240
+ test .reader = br
1241
+ t .Cleanup (func () {
1242
+ <- test .reqdone
1243
+ tr .CloseIdleConnections ()
1244
+ got , _ := io .ReadAll (test .reader )
1245
+ if len (got ) > 0 {
1246
+ t .Fatalf ("Transport sent unexpected bytes: %q" , got )
1265
1247
}
1266
- resp . Body . Close ( )
1248
+ } )
1267
1249
1268
- sent := len (v .body ) - body .Len ()
1269
- if v .status != resp .StatusCode {
1270
- t .Errorf ("test %d: status code should be %d but got %d. (%s)" , i , v .status , resp .StatusCode , v .path )
1271
- }
1272
- if v .sent != sent {
1273
- t .Errorf ("test %d: sent body should be %d but sent %d. (%s)" , i , v .sent , sent , v .path )
1250
+ return test
1251
+ }
1252
+
1253
+ // respond sends response lines from the server to the transport.
1254
+ func (test * transport100ContinueTest ) respond (lines ... string ) {
1255
+ for _ , line := range lines {
1256
+ if _ , err := test .conn .Write ([]byte (line + "\r \n " )); err != nil {
1257
+ test .t .Fatalf ("Write: %v" , err )
1274
1258
}
1275
1259
}
1260
+ if _ , err := test .conn .Write ([]byte ("\r \n " )); err != nil {
1261
+ test .t .Fatalf ("Write: %v" , err )
1262
+ }
1263
+ }
1264
+
1265
+ // wantBodySent ensures the transport has sent the request body to the server.
1266
+ func (test * transport100ContinueTest ) wantBodySent () {
1267
+ got , err := io .ReadAll (io .LimitReader (test .reader , int64 (len (transport100ContinueTestBody ))))
1268
+ if err != nil {
1269
+ test .t .Fatalf ("unexpected error reading body: %v" , err )
1270
+ }
1271
+ if got , want := string (got ), transport100ContinueTestBody ; got != want {
1272
+ test .t .Fatalf ("unexpected body: got %q, want %q" , got , want )
1273
+ }
1274
+ }
1275
+
1276
+ // wantRequestDone ensures the Transport.RoundTrip has completed with the expected status.
1277
+ func (test * transport100ContinueTest ) wantRequestDone (want int ) {
1278
+ <- test .reqdone
1279
+ if test .respErr != nil {
1280
+ test .t .Fatalf ("unexpected RoundTrip error: %v" , test .respErr )
1281
+ }
1282
+ if got := test .resp .StatusCode ; got != want {
1283
+ test .t .Fatalf ("unexpected response code: got %v, want %v" , got , want )
1284
+ }
1285
+ }
1286
+
1287
+ func TestTransportExpect100ContinueSent (t * testing.T ) {
1288
+ test := newTransport100ContinueTest (t , 1 * time .Hour )
1289
+ // Server sends a 100 Continue response, and the client sends the request body.
1290
+ test .respond ("HTTP/1.1 100 Continue" )
1291
+ test .wantBodySent ()
1292
+ test .respond ("HTTP/1.1 200" , "Content-Length: 0" )
1293
+ test .wantRequestDone (200 )
1294
+ }
1295
+
1296
+ func TestTransportExpect100Continue200ResponseNoConnClose (t * testing.T ) {
1297
+ test := newTransport100ContinueTest (t , 1 * time .Hour )
1298
+ // No 100 Continue response, no Connection: close header.
1299
+ test .respond ("HTTP/1.1 200" , "Content-Length: 0" )
1300
+ test .wantBodySent ()
1301
+ test .wantRequestDone (200 )
1302
+ }
1303
+
1304
+ func TestTransportExpect100Continue200ResponseWithConnClose (t * testing.T ) {
1305
+ test := newTransport100ContinueTest (t , 1 * time .Hour )
1306
+ // No 100 Continue response, Connection: close header set.
1307
+ test .respond ("HTTP/1.1 200" , "Connection: close" , "Content-Length: 0" )
1308
+ test .wantRequestDone (200 )
1309
+ }
1310
+
1311
+ func TestTransportExpect100Continue500ResponseNoConnClose (t * testing.T ) {
1312
+ test := newTransport100ContinueTest (t , 1 * time .Hour )
1313
+ // No 100 Continue response, no Connection: close header.
1314
+ test .respond ("HTTP/1.1 500" , "Content-Length: 0" )
1315
+ test .wantBodySent ()
1316
+ test .wantRequestDone (500 )
1317
+ }
1318
+
1319
+ func TestTransportExpect100Continue500ResponseTimeout (t * testing.T ) {
1320
+ test := newTransport100ContinueTest (t , 5 * time .Millisecond ) // short timeout
1321
+ test .wantBodySent () // after timeout
1322
+ test .respond ("HTTP/1.1 200" , "Content-Length: 0" )
1323
+ test .wantRequestDone (200 )
1276
1324
}
1277
1325
1278
1326
func TestSOCKS5Proxy (t * testing.T ) {
0 commit comments