@@ -984,13 +984,14 @@ await connection.WriteStringAsync(
984
984
}
985
985
986
986
[ Theory ]
987
- [ InlineData ( true , true ) ]
988
- [ InlineData ( true , false ) ]
989
- [ InlineData ( false , true ) ]
990
- [ InlineData ( false , false ) ]
991
- [ InlineData ( null , false ) ]
987
+ [ InlineData ( true , true , true ) ]
988
+ [ InlineData ( true , true , false ) ]
989
+ [ InlineData ( true , false , false ) ]
990
+ [ InlineData ( false , true , false ) ]
991
+ [ InlineData ( false , false , false ) ]
992
+ [ InlineData ( null , false , false ) ]
992
993
[ ActiveIssue ( "https://github.com/dotnet/runtime/issues/65429" , typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsNodeJS ) ) ]
993
- public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream ( bool ? chunked , bool enableWasmStreaming )
994
+ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream ( bool ? chunked , bool enableWasmStreaming , bool slowChunks )
994
995
{
995
996
if ( IsWinHttpHandler && UseVersion >= HttpVersion20 . Value )
996
997
{
@@ -1003,6 +1004,13 @@ public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(boo
1003
1004
return ;
1004
1005
}
1005
1006
1007
+ if ( enableWasmStreaming && ! PlatformDetection . IsBrowser )
1008
+ {
1009
+ // enableWasmStreaming makes only sense on Browser platform
1010
+ return ;
1011
+ }
1012
+
1013
+ var tcs = new TaskCompletionSource < bool > ( ) ;
1006
1014
await LoopbackServerFactory . CreateClientAndServerAsync ( async uri =>
1007
1015
{
1008
1016
var request = new HttpRequestMessage ( HttpMethod . Get , uri ) { Version = UseVersion } ;
@@ -1079,11 +1087,21 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
1079
1087
1080
1088
// Various forms of reading
1081
1089
var buffer = new byte [ 1 ] ;
1090
+ var buffer2 = new byte [ 2 ] ;
1082
1091
1083
1092
if ( PlatformDetection . IsBrowser )
1084
1093
{
1085
1094
#if ! NETFRAMEWORK
1086
- Assert . Equal ( 'h' , await responseStream . ReadByteAsync ( ) ) ;
1095
+ if ( slowChunks )
1096
+ {
1097
+ Assert . Equal ( 1 , await responseStream . ReadAsync ( new Memory < byte > ( buffer2 ) ) ) ;
1098
+ Assert . Equal ( ( byte ) 'h' , buffer2 [ 0 ] ) ;
1099
+ tcs . SetResult ( true ) ;
1100
+ }
1101
+ else
1102
+ {
1103
+ Assert . Equal ( 'h' , await responseStream . ReadByteAsync ( ) ) ;
1104
+ }
1087
1105
Assert . Equal ( 'e' , await responseStream . ReadByteAsync ( ) ) ;
1088
1106
Assert . Equal ( 1 , await responseStream . ReadAsync ( new Memory < byte > ( buffer ) ) ) ;
1089
1107
Assert . Equal ( ( byte ) 'l' , buffer [ 0 ] ) ;
@@ -1184,7 +1202,18 @@ await server.AcceptConnectionAsync(async connection =>
1184
1202
{
1185
1203
case true :
1186
1204
await connection . SendResponseAsync ( HttpStatusCode . OK , headers : new HttpHeaderData [ ] { new HttpHeaderData ( "Transfer-Encoding" , "chunked" ) } , isFinal : false ) ;
1187
- await connection . SendResponseBodyAsync ( "3\r \n hel\r \n 8\r \n lo world\r \n 0\r \n \r \n " ) ;
1205
+ if ( PlatformDetection . IsBrowser && slowChunks )
1206
+ {
1207
+ await connection . SendResponseBodyAsync ( "1\r \n h\r \n " , false ) ;
1208
+ await tcs . Task ;
1209
+ await connection . SendResponseBodyAsync ( "2\r \n el\r \n " , false ) ;
1210
+ await connection . SendResponseBodyAsync ( "8\r \n lo world\r \n " , false ) ;
1211
+ await connection . SendResponseBodyAsync ( "0\r \n \r \n " , true ) ;
1212
+ }
1213
+ else
1214
+ {
1215
+ await connection . SendResponseBodyAsync ( "3\r \n hel\r \n 8\r \n lo world\r \n 0\r \n \r \n " ) ;
1216
+ }
1188
1217
break ;
1189
1218
1190
1219
case false :
@@ -1295,6 +1324,80 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri =>
1295
1324
server => server . AcceptConnectionSendResponseAndCloseAsync ( ) ) ;
1296
1325
}
1297
1326
1327
+ [ ConditionalFact ( typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsBrowser ) ) ]
1328
+ [ ActiveIssue ( "https://github.com/dotnet/runtime/issues/65429" , typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsNodeJS ) ) ]
1329
+ public async Task ReadAsStreamAsync_StreamingCancellation ( )
1330
+ {
1331
+ var tcs = new TaskCompletionSource < bool > ( ) ;
1332
+ var tcs2 = new TaskCompletionSource < bool > ( ) ;
1333
+ await LoopbackServerFactory . CreateClientAndServerAsync ( async uri =>
1334
+ {
1335
+ var request = new HttpRequestMessage ( HttpMethod . Get , uri ) { Version = UseVersion } ;
1336
+ #if ! NETFRAMEWORK
1337
+ request . Options . Set ( new HttpRequestOptionsKey < bool > ( "WebAssemblyEnableStreamingResponse" ) , true ) ;
1338
+ #endif
1339
+
1340
+ var cts = new CancellationTokenSource ( ) ;
1341
+ using ( var client = new HttpMessageInvoker ( CreateHttpClientHandler ( ) ) )
1342
+ using ( HttpResponseMessage response = await client . SendAsync ( TestAsync , request , CancellationToken . None ) )
1343
+ {
1344
+ using ( Stream responseStream = await response . Content . ReadAsStreamAsync ( TestAsync ) )
1345
+ {
1346
+ var buffer = new byte [ 1 ] ;
1347
+ #if ! NETFRAMEWORK
1348
+ Assert . Equal ( 1 , await responseStream . ReadAsync ( new Memory < byte > ( buffer ) ) ) ;
1349
+ Assert . Equal ( ( byte ) 'h' , buffer [ 0 ] ) ;
1350
+ var sizePromise = responseStream . ReadAsync ( new Memory < byte > ( buffer ) , cts . Token ) ;
1351
+ await tcs2 . Task ; // wait for the request and response header to be sent
1352
+ cts . Cancel ( ) ;
1353
+ await Assert . ThrowsAsync < TaskCanceledException > ( async ( ) => await sizePromise ) ;
1354
+ tcs . SetResult ( true ) ;
1355
+ #endif
1356
+ }
1357
+ }
1358
+ } , async server =>
1359
+ {
1360
+ await server . AcceptConnectionAsync ( async connection =>
1361
+ {
1362
+ await connection . ReadRequestDataAsync ( ) ;
1363
+ await connection . SendResponseAsync ( HttpStatusCode . OK , headers : new HttpHeaderData [ ] { new HttpHeaderData ( "Transfer-Encoding" , "chunked" ) } , isFinal : false ) ;
1364
+ await connection . SendResponseBodyAsync ( "1\r \n h\r \n " , false ) ;
1365
+ tcs2 . SetResult ( true ) ;
1366
+ await tcs . Task ;
1367
+ } ) ;
1368
+ } ) ;
1369
+ }
1370
+
1371
+ [ ConditionalFact ( typeof ( PlatformDetection ) , nameof ( PlatformDetection . IsBrowser ) ) ]
1372
+ public async Task ReadAsStreamAsync_Cancellation ( )
1373
+ {
1374
+ var tcs = new TaskCompletionSource < bool > ( ) ;
1375
+ var tcs2 = new TaskCompletionSource < bool > ( ) ;
1376
+ await LoopbackServerFactory . CreateClientAndServerAsync ( async uri =>
1377
+ {
1378
+ var request = new HttpRequestMessage ( HttpMethod . Get , uri ) { Version = UseVersion } ;
1379
+ var cts = new CancellationTokenSource ( ) ;
1380
+ using ( var client = new HttpMessageInvoker ( CreateHttpClientHandler ( ) ) )
1381
+ {
1382
+ var responsePromise = client . SendAsync ( TestAsync , request , cts . Token ) ;
1383
+ await tcs2 . Task ; // wait for the request to be sent
1384
+ cts . Cancel ( ) ;
1385
+ await Assert . ThrowsAsync < TaskCanceledException > ( async ( ) => await responsePromise ) ;
1386
+ tcs . SetResult ( true ) ;
1387
+ }
1388
+ } , async server =>
1389
+ {
1390
+ await server . AcceptConnectionAsync ( async connection =>
1391
+ {
1392
+ await connection . ReadRequestDataAsync ( ) ;
1393
+ tcs2 . SetResult ( true ) ;
1394
+ await connection . SendResponseAsync ( HttpStatusCode . OK , headers : new HttpHeaderData [ ] { new HttpHeaderData ( "Transfer-Encoding" , "chunked" ) } , isFinal : false ) ;
1395
+ await connection . SendResponseBodyAsync ( "1\r \n h\r \n " , false ) ;
1396
+ await tcs . Task ;
1397
+ } ) ;
1398
+ } ) ;
1399
+ }
1400
+
1298
1401
[ Fact ]
1299
1402
[ ActiveIssue ( "https://github.com/dotnet/runtime/issues/58812" , TestPlatforms . Browser ) ]
1300
1403
public async Task Dispose_DisposingHandlerCancelsActiveOperationsWithoutResponses ( )
0 commit comments