@@ -16,6 +16,7 @@ import AsyncHTTPClient
16
16
import NIO
17
17
import NIOFoundationCompat
18
18
import NIOHTTP1
19
+ import NIOSSL
19
20
import XCTest
20
21
21
22
class HTTPClientTests : XCTestCase {
@@ -346,4 +347,141 @@ class HTTPClientTests: XCTestCase {
346
347
XCTAssertEqual ( . ok, response. status)
347
348
XCTAssertEqual ( " 12344321 " , data. data)
348
349
}
350
+
351
+ func testNoContentLengthForSSLUncleanShutdown( ) throws {
352
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
353
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
354
+ configuration: HTTPClient . Configuration ( certificateVerification: . none) )
355
+
356
+ defer {
357
+ try ! httpClient. syncShutdown ( )
358
+ httpBin. shutdown ( )
359
+ }
360
+
361
+ XCTAssertThrowsError ( try httpClient. get ( url: " https://localhost: \( httpBin. port) /nocontentlength " ) . wait ( ) , " Should fail " ) { error in
362
+ guard case let error = error as? NIOSSLError , error == . uncleanShutdown else {
363
+ return XCTFail ( " Should fail with NIOSSLError.uncleanShutdown " )
364
+ }
365
+ }
366
+ }
367
+
368
+ func testNoContentLengthWithIgnoreErrorForSSLUncleanShutdown( ) throws {
369
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
370
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
371
+ configuration: HTTPClient . Configuration ( certificateVerification: . none, ignoreUncleanSSLShutdown: true ) )
372
+
373
+ defer {
374
+ try ! httpClient. syncShutdown ( )
375
+ httpBin. shutdown ( )
376
+ }
377
+
378
+ let response = try httpClient. get ( url: " https://localhost: \( httpBin. port) /nocontentlength " ) . wait ( )
379
+ let bytes = response. body. flatMap { $0. getData ( at: 0 , length: $0. readableBytes) }
380
+ let string = String ( decoding: bytes!, as: UTF8 . self)
381
+
382
+ XCTAssertEqual ( . ok, response. status)
383
+ XCTAssertEqual ( " foo " , string)
384
+ }
385
+
386
+ func testCorrectContentLengthForSSLUncleanShutdown( ) throws {
387
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
388
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
389
+ configuration: HTTPClient . Configuration ( certificateVerification: . none) )
390
+
391
+ defer {
392
+ try ! httpClient. syncShutdown ( )
393
+ httpBin. shutdown ( )
394
+ }
395
+
396
+ let response = try httpClient. get ( url: " https://localhost: \( httpBin. port) / " ) . wait ( )
397
+ let bytes = response. body. flatMap { $0. getData ( at: 0 , length: $0. readableBytes) }
398
+ let string = String ( decoding: bytes!, as: UTF8 . self)
399
+
400
+ XCTAssertEqual ( . notFound, response. status)
401
+ XCTAssertEqual ( " Not Found " , string)
402
+ }
403
+
404
+ func testNoContentForSSLUncleanShutdown( ) throws {
405
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
406
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
407
+ configuration: HTTPClient . Configuration ( certificateVerification: . none) )
408
+
409
+ defer {
410
+ try ! httpClient. syncShutdown ( )
411
+ httpBin. shutdown ( )
412
+ }
413
+
414
+ let response = try httpClient. get ( url: " https://localhost: \( httpBin. port) /nocontent " ) . wait ( )
415
+
416
+ XCTAssertEqual ( . noContent, response. status)
417
+ XCTAssertEqual ( response. body, nil )
418
+ }
419
+
420
+ func testNoResponseForSSLUncleanShutdown( ) throws {
421
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
422
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
423
+ configuration: HTTPClient . Configuration ( certificateVerification: . none) )
424
+
425
+ defer {
426
+ try ! httpClient. syncShutdown ( )
427
+ httpBin. shutdown ( )
428
+ }
429
+
430
+ XCTAssertThrowsError ( try httpClient. get ( url: " https://localhost: \( httpBin. port) /noresponse " ) . wait ( ) , " Should fail " ) { error in
431
+ guard case let error = error as? NIOSSLError , error == . uncleanShutdown else {
432
+ return XCTFail ( " Should fail with NIOSSLError.uncleanShutdown " )
433
+ }
434
+ }
435
+ }
436
+
437
+ func testNoResponseWithIgnoreErrorForSSLUncleanShutdown( ) throws {
438
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
439
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
440
+ configuration: HTTPClient . Configuration ( certificateVerification: . none, ignoreUncleanSSLShutdown: true ) )
441
+
442
+ defer {
443
+ try ! httpClient. syncShutdown ( )
444
+ httpBin. shutdown ( )
445
+ }
446
+
447
+ XCTAssertThrowsError ( try httpClient. get ( url: " https://localhost: \( httpBin. port) /noresponse " ) . wait ( ) , " Should fail " ) { error in
448
+ guard case let error = error as? NIOSSLError , error == . uncleanShutdown else {
449
+ return XCTFail ( " Should fail with NIOSSLError.uncleanShutdown " )
450
+ }
451
+ }
452
+ }
453
+
454
+ func testWrongContentLengthForSSLUncleanShutdown( ) throws {
455
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
456
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
457
+ configuration: HTTPClient . Configuration ( certificateVerification: . none) )
458
+
459
+ defer {
460
+ try ! httpClient. syncShutdown ( )
461
+ httpBin. shutdown ( )
462
+ }
463
+
464
+ XCTAssertThrowsError ( try httpClient. get ( url: " https://localhost: \( httpBin. port) /wrongcontentlength " ) . wait ( ) , " Should fail " ) { error in
465
+ guard case let error = error as? NIOSSLError , error == . uncleanShutdown else {
466
+ return XCTFail ( " Should fail with NIOSSLError.uncleanShutdown " )
467
+ }
468
+ }
469
+ }
470
+
471
+ func testWrongContentLengthWithIgnoreErrorForSSLUncleanShutdown( ) throws {
472
+ let httpBin = HttpBinForSSLUncleanShutdown ( )
473
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . createNew,
474
+ configuration: HTTPClient . Configuration ( certificateVerification: . none, ignoreUncleanSSLShutdown: true ) )
475
+
476
+ defer {
477
+ try ! httpClient. syncShutdown ( )
478
+ httpBin. shutdown ( )
479
+ }
480
+
481
+ XCTAssertThrowsError ( try httpClient. get ( url: " https://localhost: \( httpBin. port) /wrongcontentlength " ) . wait ( ) , " Should fail " ) { error in
482
+ guard case let error = error as? HTTPParserError , error == . invalidEOFState else {
483
+ return XCTFail ( " Should fail with HTTPParserError.invalidEOFState " )
484
+ }
485
+ }
486
+ }
349
487
}
0 commit comments