@@ -18,11 +18,25 @@ import NIOFoundationCompat
18
18
import NIOHTTP1
19
19
import NIOHTTPCompression
20
20
import NIOSSL
21
+ import NIOTestUtils
21
22
import XCTest
22
23
23
24
class HTTPClientTests : XCTestCase {
24
25
typealias Request = HTTPClient . Request
25
26
27
+ var group : EventLoopGroup !
28
+
29
+ override func setUp( ) {
30
+ XCTAssertNil ( self . group)
31
+ self . group = MultiThreadedEventLoopGroup ( numberOfThreads: 1 )
32
+ }
33
+
34
+ override func tearDown( ) {
35
+ XCTAssertNotNil ( self . group)
36
+ XCTAssertNoThrow ( try self . group. syncShutdownGracefully ( ) )
37
+ self . group = nil
38
+ }
39
+
26
40
func testRequestURI( ) throws {
27
41
let request1 = try Request ( url: " https://someserver.com:8888/some/path?foo=bar " )
28
42
XCTAssertEqual ( request1. url. host, " someserver.com " )
@@ -658,4 +672,172 @@ class HTTPClientTests: XCTestCase {
658
672
XCTAssertEqual ( error as! HTTPClientError , HTTPClientError . redirectLimitReached)
659
673
}
660
674
}
675
+
676
+ func testWorksWith500Error( ) {
677
+ let web = NIOHTTP1TestServer ( group: self . group)
678
+ defer {
679
+ XCTAssertNoThrow ( try web. stop ( ) )
680
+ }
681
+
682
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . shared( self . group) )
683
+ defer {
684
+ XCTAssertNoThrow ( try httpClient. syncShutdown ( ) )
685
+ }
686
+ let result = httpClient. get ( url: " http://localhost: \( web. serverPort) /foo " )
687
+
688
+ XCTAssertNoThrow ( XCTAssertEqual ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
689
+ method: . GET,
690
+ uri: " /foo " ,
691
+ headers: HTTPHeaders ( [ ( " Host " , " localhost " ) ,
692
+ // The following line can be removed once we
693
+ // have a connection pool.
694
+ ( " Connection " , " close " ) ,
695
+ ( " Content-Length " , " 0 " ) ] ) ) ) ,
696
+ try web. readInbound ( ) ) )
697
+ XCTAssertNoThrow ( XCTAssertEqual ( . end( nil ) ,
698
+ try web. readInbound ( ) ) )
699
+ XCTAssertNoThrow ( try web. writeOutbound ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
700
+ status: . internalServerError) ) ) )
701
+ XCTAssertNoThrow ( try web. writeOutbound ( . end( nil ) ) )
702
+
703
+ var response : HTTPClient . Response ?
704
+ XCTAssertNoThrow ( response = try result. wait ( ) )
705
+ XCTAssertEqual ( . internalServerError, response? . status)
706
+ XCTAssertNil ( response? . body)
707
+ }
708
+
709
+ func testWorksWithHTTP10Response( ) {
710
+ let web = NIOHTTP1TestServer ( group: self . group)
711
+ defer {
712
+ XCTAssertNoThrow ( try web. stop ( ) )
713
+ }
714
+
715
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . shared( self . group) )
716
+ defer {
717
+ XCTAssertNoThrow ( try httpClient. syncShutdown ( ) )
718
+ }
719
+ let result = httpClient. get ( url: " http://localhost: \( web. serverPort) /foo " )
720
+
721
+ XCTAssertNoThrow ( XCTAssertEqual ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
722
+ method: . GET,
723
+ uri: " /foo " ,
724
+ headers: HTTPHeaders ( [ ( " Host " , " localhost " ) ,
725
+ // The following line can be removed once we
726
+ // have a connection pool.
727
+ ( " Connection " , " close " ) ,
728
+ ( " Content-Length " , " 0 " ) ] ) ) ) ,
729
+ try web. readInbound ( ) ) )
730
+ XCTAssertNoThrow ( XCTAssertEqual ( . end( nil ) ,
731
+ try web. readInbound ( ) ) )
732
+ XCTAssertNoThrow ( try web. writeOutbound ( . head( . init( version: . init( major: 1 , minor: 0 ) ,
733
+ status: . internalServerError) ) ) )
734
+ XCTAssertNoThrow ( try web. writeOutbound ( . end( nil ) ) )
735
+
736
+ var response : HTTPClient . Response ?
737
+ XCTAssertNoThrow ( response = try result. wait ( ) )
738
+ XCTAssertEqual ( . internalServerError, response? . status)
739
+ XCTAssertNil ( response? . body)
740
+ }
741
+
742
+ func testWorksWhenServerClosesConnectionAfterReceivingRequest( ) {
743
+ let web = NIOHTTP1TestServer ( group: self . group)
744
+
745
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . shared( self . group) )
746
+ defer {
747
+ XCTAssertNoThrow ( try httpClient. syncShutdown ( ) )
748
+ }
749
+ let result = httpClient. get ( url: " http://localhost: \( web. serverPort) /foo " )
750
+
751
+ XCTAssertNoThrow ( XCTAssertEqual ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
752
+ method: . GET,
753
+ uri: " /foo " ,
754
+ headers: HTTPHeaders ( [ ( " Host " , " localhost " ) ,
755
+ // The following line can be removed once we
756
+ // have a connection pool.
757
+ ( " Connection " , " close " ) ,
758
+ ( " Content-Length " , " 0 " ) ] ) ) ) ,
759
+ try web. readInbound ( ) ) )
760
+ XCTAssertNoThrow ( XCTAssertEqual ( . end( nil ) ,
761
+ try web. readInbound ( ) ) )
762
+ XCTAssertNoThrow ( try web. stop ( ) )
763
+
764
+ XCTAssertThrowsError ( try result. wait ( ) ) { error in
765
+ XCTAssertEqual ( HTTPClientError . remoteConnectionClosed, error as? HTTPClientError )
766
+ }
767
+ }
768
+
769
+ func testSubsequentRequestsWorkWithServerSendingConnectionClose( ) {
770
+ let web = NIOHTTP1TestServer ( group: self . group)
771
+ defer {
772
+ XCTAssertNoThrow ( try web. stop ( ) )
773
+ }
774
+
775
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . shared( self . group) )
776
+ defer {
777
+ XCTAssertNoThrow ( try httpClient. syncShutdown ( ) )
778
+ }
779
+
780
+ for _ in 0 ..< 10 {
781
+ let result = httpClient. get ( url: " http://localhost: \( web. serverPort) /foo " )
782
+
783
+ XCTAssertNoThrow ( XCTAssertEqual ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
784
+ method: . GET,
785
+ uri: " /foo " ,
786
+ headers: HTTPHeaders ( [ ( " Host " , " localhost " ) ,
787
+ // The following line can be removed once
788
+ // we have a connection pool.
789
+ ( " Connection " , " close " ) ,
790
+ ( " Content-Length " , " 0 " ) ] ) ) ) ,
791
+ try web. readInbound ( ) ) )
792
+ XCTAssertNoThrow ( XCTAssertEqual ( . end( nil ) ,
793
+ try web. readInbound ( ) ) )
794
+ XCTAssertNoThrow ( try web. writeOutbound ( . head( . init( version: . init( major: 1 , minor: 0 ) ,
795
+ status: . ok,
796
+ headers: HTTPHeaders ( [ ( " connection " , " close " ) ] ) ) ) ) )
797
+ XCTAssertNoThrow ( try web. writeOutbound ( . end( nil ) ) )
798
+
799
+ var response : HTTPClient . Response ?
800
+ XCTAssertNoThrow ( response = try result. wait ( ) )
801
+ XCTAssertEqual ( . ok, response? . status)
802
+ XCTAssertNil ( response? . body)
803
+ }
804
+ }
805
+
806
+ func testSubsequentRequestsWorkWithServerAlternatingBetweenKeepAliveAndClose( ) {
807
+ let web = NIOHTTP1TestServer ( group: self . group)
808
+ defer {
809
+ XCTAssertNoThrow ( try web. stop ( ) )
810
+ }
811
+
812
+ let httpClient = HTTPClient ( eventLoopGroupProvider: . shared( self . group) )
813
+ defer {
814
+ XCTAssertNoThrow ( try httpClient. syncShutdown ( ) )
815
+ }
816
+
817
+ for i in 0 ..< 10 {
818
+ let result = httpClient. get ( url: " http://localhost: \( web. serverPort) /foo " )
819
+
820
+ XCTAssertNoThrow ( XCTAssertEqual ( . head( . init( version: . init( major: 1 , minor: 1 ) ,
821
+ method: . GET,
822
+ uri: " /foo " ,
823
+ headers: HTTPHeaders ( [ ( " Host " , " localhost " ) ,
824
+ // The following line can be removed once
825
+ // we have a connection pool.
826
+ ( " Connection " , " close " ) ,
827
+ ( " Content-Length " , " 0 " ) ] ) ) ) ,
828
+ try web. readInbound ( ) ) )
829
+ XCTAssertNoThrow ( XCTAssertEqual ( . end( nil ) ,
830
+ try web. readInbound ( ) ) )
831
+ XCTAssertNoThrow ( try web. writeOutbound ( . head( . init( version: . init( major: 1 , minor: 0 ) ,
832
+ status: . ok,
833
+ headers: HTTPHeaders ( [ ( " connection " ,
834
+ i % 2 == 0 ? " close " : " keep-alive " ) ] ) ) ) ) )
835
+ XCTAssertNoThrow ( try web. writeOutbound ( . end( nil ) ) )
836
+
837
+ var response : HTTPClient . Response ?
838
+ XCTAssertNoThrow ( response = try result. wait ( ) )
839
+ XCTAssertEqual ( . ok, response? . status)
840
+ XCTAssertNil ( response? . body)
841
+ }
842
+ }
661
843
}
0 commit comments