4444import software .amazon .awssdk .crt .Log ;
4545
4646public class Http2ClientLocalHostTest extends HttpClientTestFixture {
47- // crt/aws-c-http/tests/mock_server includes a readme on how the server can be run locally for testing.
47+ // crt/aws-c-http/tests/mock_server includes a readme on how the server can be
48+ // run locally for testing.
4849 private static final int LOCAL_HTTPS_PORT = 3443 ;
4950 private static final int LOCAL_HTTP_PORT = 3280 ;
5051
@@ -208,7 +209,7 @@ public void onResponseHeaders(HttpStreamBase stream, int responseStatusCode, int
208209 }
209210
210211 @ Override
211- public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ){
212+ public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ) {
212213 String bodyString = new String (bodyBytesIn );
213214 // Parse {"bytes": 123456} manually
214215 int start = bodyString .indexOf ("\" bytes\" :" ) + 8 ;
@@ -255,33 +256,34 @@ public void testRequestsUploadStress() throws Exception {
255256
256257 final CompletableFuture <Void > requestCompleteFuture = new CompletableFuture <Void >();
257258 final long expectedLength = bodyLength ;
258- CompletableFuture <Http2Stream > acquireCompleteFuture = streamManager .acquireStream (request , new HttpStreamBaseResponseHandler () {
259- @ Override
260- public void onResponseHeaders (HttpStreamBase stream , int responseStatusCode , int blockType ,
261- HttpHeader [] nextHeaders ) {
259+ CompletableFuture <Http2Stream > acquireCompleteFuture = streamManager .acquireStream (request ,
260+ new HttpStreamBaseResponseHandler () {
261+ @ Override
262+ public void onResponseHeaders (HttpStreamBase stream , int responseStatusCode , int blockType ,
263+ HttpHeader [] nextHeaders ) {
262264
263- Assert .assertTrue (responseStatusCode == 200 );
264- }
265+ Assert .assertTrue (responseStatusCode == 200 );
266+ }
265267
266- @ Override
267- public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ){
268- String bodyString = new String (bodyBytesIn );
269- // Parse {"bytes": 123456} manually
270- int start = bodyString .indexOf ("\" bytes\" :" ) + 8 ;
271- int end = bodyString .indexOf ("}" , start );
272- String bytesStr = bodyString .substring (start , end ).trim ();
273- long receivedLength = Long .parseLong (bytesStr );
274- Assert .assertTrue (receivedLength == expectedLength );
275- return bodyString .length ();
276- }
268+ @ Override
269+ public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ) {
270+ String bodyString = new String (bodyBytesIn );
271+ // Parse {"bytes": 123456} manually
272+ int start = bodyString .indexOf ("\" bytes\" :" ) + 8 ;
273+ int end = bodyString .indexOf ("}" , start );
274+ String bytesStr = bodyString .substring (start , end ).trim ();
275+ long receivedLength = Long .parseLong (bytesStr );
276+ Assert .assertTrue (receivedLength == expectedLength );
277+ return bodyString .length ();
278+ }
277279
278- @ Override
279- public void onResponseComplete (HttpStreamBase stream , int errorCode ) {
280- Assert .assertTrue (errorCode == CRT .AWS_CRT_SUCCESS );
281- stream .close ();
282- requestCompleteFuture .complete (null );
283- }
284- });
280+ @ Override
281+ public void onResponseComplete (HttpStreamBase stream , int errorCode ) {
282+ Assert .assertTrue (errorCode == CRT .AWS_CRT_SUCCESS );
283+ stream .close ();
284+ requestCompleteFuture .complete (null );
285+ }
286+ });
285287
286288 acquireCompleteFuture .get (30 , TimeUnit .SECONDS );
287289 requestCompleteFuture .get (5 , TimeUnit .MINUTES );
@@ -305,29 +307,30 @@ public void testRequestsDownloadStress() throws Exception {
305307
306308 final CompletableFuture <Void > requestCompleteFuture = new CompletableFuture <Void >();
307309 final AtomicLong receivedLength = new AtomicLong (0 );
308- CompletableFuture <Http2Stream > acquireCompleteFuture = streamManager .acquireStream (request , new HttpStreamBaseResponseHandler () {
309- @ Override
310- public void onResponseHeaders (HttpStreamBase stream , int responseStatusCode , int blockType ,
311- HttpHeader [] nextHeaders ) {
310+ CompletableFuture <Http2Stream > acquireCompleteFuture = streamManager .acquireStream (request ,
311+ new HttpStreamBaseResponseHandler () {
312+ @ Override
313+ public void onResponseHeaders (HttpStreamBase stream , int responseStatusCode , int blockType ,
314+ HttpHeader [] nextHeaders ) {
312315
313- Assert .assertTrue (responseStatusCode == 200 );
314- }
316+ Assert .assertTrue (responseStatusCode == 200 );
317+ }
315318
316- @ Override
317- public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ){
318- receivedLength .addAndGet (bodyBytesIn .length );
319+ @ Override
320+ public int onResponseBody (HttpStreamBase stream , byte [] bodyBytesIn ) {
321+ receivedLength .addAndGet (bodyBytesIn .length );
319322
320- return bodyBytesIn .length ;
321- }
323+ return bodyBytesIn .length ;
324+ }
322325
323- @ Override
324- public void onResponseComplete (HttpStreamBase stream , int errorCode ) {
326+ @ Override
327+ public void onResponseComplete (HttpStreamBase stream , int errorCode ) {
325328
326- Assert .assertTrue (errorCode == CRT .AWS_CRT_SUCCESS );
327- stream .close ();
328- requestCompleteFuture .complete (null );
329- }
330- });
329+ Assert .assertTrue (errorCode == CRT .AWS_CRT_SUCCESS );
330+ stream .close ();
331+ requestCompleteFuture .complete (null );
332+ }
333+ });
331334
332335 acquireCompleteFuture .get (30 , TimeUnit .SECONDS );
333336 requestCompleteFuture .get (5 , TimeUnit .MINUTES );
@@ -337,4 +340,45 @@ public void onResponseComplete(HttpStreamBase stream, int errorCode) {
337340 CrtResource .logNativeResources ();
338341 CrtResource .waitForNoResources ();
339342 }
343+
344+ @ Test
345+ public void testHttp2StreamCancel () throws Exception {
346+ skipIfAndroid ();
347+ skipIfLocalhostUnavailable ();
348+ URI uri = new URI (String .format ("https://localhost:%d/echo" , LOCAL_HTTPS_PORT ));
349+ try (Http2StreamManager streamManager = createStreamManager (uri , 100 )) {
350+ long bodyLength = 250000L ;
351+
352+ Http2Request request = createHttp2Request ("GET" , uri , 0 );
353+ request .addHeader (new HttpHeader ("x-repeat-data" , String .valueOf (bodyLength )));
354+ /* Get a slow response to make sure we cancel before finishes */
355+ request .addHeader (new HttpHeader ("x-slow-response" , "true" ));
356+
357+ final CompletableFuture <Void > requestCompleteFuture = new CompletableFuture <Void >();
358+ final int expectedErrorCode = 0x0832 ; // Some Random error code
359+ CompletableFuture <Http2Stream > acquireCompleteFuture = streamManager .acquireStream (request ,
360+ new HttpStreamBaseResponseHandler () {
361+ @ Override
362+ public void onResponseHeaders (HttpStreamBase stream , int responseStatusCode , int blockType ,
363+ HttpHeader [] nextHeaders ) {
364+ // Cancel the HTTP/2 stream immediately upon receiving headers with specific
365+ // error code
366+ stream .cancel (expectedErrorCode );
367+ }
368+
369+ @ Override
370+ public void onResponseComplete (HttpStreamBase stream , int errorCode ) {
371+
372+ Assert .assertTrue (errorCode == expectedErrorCode );
373+ stream .close ();
374+ requestCompleteFuture .complete (null );
375+ }
376+ });
377+
378+ acquireCompleteFuture .get (3 , TimeUnit .SECONDS );
379+ requestCompleteFuture .get (10 , TimeUnit .SECONDS );
380+ }
381+ CrtResource .logNativeResources ();
382+ CrtResource .waitForNoResources ();
383+ }
340384}
0 commit comments