@@ -77,9 +77,7 @@ extension HTTPClient {
7777 /// - data: Body `Data` representation.
7878 public static func data( _ data: Data ) -> Body {
7979 return Body ( length: data. count) { writer in
80- var buffer = ByteBufferAllocator ( ) . buffer ( capacity: data. count)
81- buffer. writeBytes ( data)
82- return writer. write ( . byteBuffer( buffer) )
80+ writer. write ( . byteBuffer( ByteBuffer ( bytes: data) ) )
8381 }
8482 }
8583
@@ -89,9 +87,7 @@ extension HTTPClient {
8987 /// - string: Body `String` representation.
9088 public static func string( _ string: String ) -> Body {
9189 return Body ( length: string. utf8. count) { writer in
92- var buffer = ByteBufferAllocator ( ) . buffer ( capacity: string. utf8. count)
93- buffer. writeString ( string)
94- return writer. write ( . byteBuffer( buffer) )
90+ writer. write ( . byteBuffer( ByteBuffer ( string: string) ) )
9591 }
9692 }
9793 }
@@ -641,7 +637,7 @@ internal class TaskHandler<Delegate: HTTPClientResponseDelegate>: RemovableChann
641637 case head
642638 case redirected( HTTPResponseHead , URL )
643639 case body
644- case end
640+ case endOrError
645641 }
646642
647643 let task : HTTPClient . Task < Delegate . Response >
@@ -651,6 +647,8 @@ internal class TaskHandler<Delegate: HTTPClientResponseDelegate>: RemovableChann
651647 let logger : Logger // We are okay to store the logger here because a TaskHandler is just for one request.
652648
653649 var state : State = . idle
650+ var expectedBodyLength : Int ?
651+ var actualBodyLength : Int = 0
654652 var pendingRead = false
655653 var mayRead = true
656654 var closing = false {
@@ -771,16 +769,21 @@ extension TaskHandler: ChannelDuplexHandler {
771769 uri: request. uri)
772770 var headers = request. headers
773771
774- if !request. headers. contains ( name: " Host " ) {
775- headers. add ( name: " Host " , value: request. host)
772+ if !request. headers. contains ( name: " host " ) {
773+ let port = request. port
774+ var host = request. host
775+ if !( port == 80 && request. scheme == " http " ) , !( port == 443 && request. scheme == " https " ) {
776+ host += " : \( port) "
777+ }
778+ headers. add ( name: " host " , value: host)
776779 }
777780
778781 do {
779782 try headers. validate ( method: request. method, body: request. body)
780783 } catch {
781784 promise? . fail ( error)
782785 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
783- self . state = . end
786+ self . state = . endOrError
784787 return
785788 }
786789
@@ -794,12 +797,23 @@ extension TaskHandler: ChannelDuplexHandler {
794797 assert ( head. version == HTTPVersion ( major: 1 , minor: 1 ) ,
795798 " Sending a request in HTTP version \( head. version) which is unsupported by the above `if` " )
796799
800+ let contentLengths = head. headers [ canonicalForm: " content-length " ]
801+ assert ( contentLengths. count <= 1 )
802+
803+ self . expectedBodyLength = contentLengths. first. flatMap { Int ( $0) }
804+
797805 context. write ( wrapOutboundOut ( . head( head) ) ) . map {
798806 self . callOutToDelegateFireAndForget ( value: head, self . delegate. didSendRequestHead)
799807 } . flatMap {
800808 self . writeBody ( request: request, context: context)
801809 } . flatMap {
802810 context. eventLoop. assertInEventLoop ( )
811+ if let expectedBodyLength = self . expectedBodyLength, expectedBodyLength != self . actualBodyLength {
812+ self . state = . endOrError
813+ let error = HTTPClientError . bodyLengthMismatch
814+ self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
815+ return context. eventLoop. makeFailedFuture ( error)
816+ }
803817 return context. writeAndFlush ( self . wrapOutboundOut ( . end( nil ) ) )
804818 } . map {
805819 context. eventLoop. assertInEventLoop ( )
@@ -808,10 +822,10 @@ extension TaskHandler: ChannelDuplexHandler {
808822 } . flatMapErrorThrowing { error in
809823 context. eventLoop. assertInEventLoop ( )
810824 switch self . state {
811- case . end :
825+ case . endOrError :
812826 break
813827 default :
814- self . state = . end
828+ self . state = . endOrError
815829 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
816830 }
817831 throw error
@@ -828,9 +842,11 @@ extension TaskHandler: ChannelDuplexHandler {
828842 let promise = self . task. eventLoop. makePromise ( of: Void . self)
829843 // All writes have to be switched to the channel EL if channel and task ELs differ
830844 if context. eventLoop. inEventLoop {
845+ self . actualBodyLength += part. readableBytes
831846 context. writeAndFlush ( self . wrapOutboundOut ( . body( part) ) , promise: promise)
832847 } else {
833848 context. eventLoop. execute {
849+ self . actualBodyLength += part. readableBytes
834850 context. writeAndFlush ( self . wrapOutboundOut ( . body( part) ) , promise: promise)
835851 }
836852 }
@@ -893,12 +909,12 @@ extension TaskHandler: ChannelDuplexHandler {
893909 case . end:
894910 switch self . state {
895911 case . redirected( let head, let redirectURL) :
896- self . state = . end
912+ self . state = . endOrError
897913 self . task. releaseAssociatedConnection ( delegateType: Delegate . self, closing: self . closing) . whenSuccess {
898914 self . redirectHandler? . redirect ( status: head. status, to: redirectURL, promise: self . task. promise)
899915 }
900916 default :
901- self . state = . end
917+ self . state = . endOrError
902918 self . callOutToDelegate ( promise: self . task. promise, self . delegate. didFinishRequest)
903919 }
904920 }
@@ -913,14 +929,14 @@ extension TaskHandler: ChannelDuplexHandler {
913929 context. read ( )
914930 }
915931 case . failure( let error) :
916- self . state = . end
932+ self . state = . endOrError
917933 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
918934 }
919935 }
920936
921937 func userInboundEventTriggered( context: ChannelHandlerContext , event: Any ) {
922938 if ( event as? IdleStateHandler . IdleStateEvent) == . read {
923- self . state = . end
939+ self . state = . endOrError
924940 let error = HTTPClientError . readTimeout
925941 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
926942 } else {
@@ -930,7 +946,7 @@ extension TaskHandler: ChannelDuplexHandler {
930946
931947 func triggerUserOutboundEvent( context: ChannelHandlerContext , event: Any , promise: EventLoopPromise < Void > ? ) {
932948 if ( event as? TaskCancelEvent ) != nil {
933- self . state = . end
949+ self . state = . endOrError
934950 let error = HTTPClientError . cancelled
935951 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
936952 promise? . succeed ( ( ) )
@@ -941,10 +957,10 @@ extension TaskHandler: ChannelDuplexHandler {
941957
942958 func channelInactive( context: ChannelHandlerContext ) {
943959 switch self . state {
944- case . end :
960+ case . endOrError :
945961 break
946962 case . body, . head, . idle, . redirected, . sent:
947- self . state = . end
963+ self . state = . endOrError
948964 let error = HTTPClientError . remoteConnectionClosed
949965 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
950966 }
@@ -955,7 +971,7 @@ extension TaskHandler: ChannelDuplexHandler {
955971 switch error {
956972 case NIOSSLError . uncleanShutdown:
957973 switch self . state {
958- case . end :
974+ case . endOrError :
959975 /// Some HTTP Servers can 'forget' to respond with CloseNotify when client is closing connection,
960976 /// this could lead to incomplete SSL shutdown. But since request is already processed, we can ignore this error.
961977 break
@@ -964,11 +980,11 @@ extension TaskHandler: ChannelDuplexHandler {
964980 /// We can also ignore this error like `.end`.
965981 break
966982 default :
967- self . state = . end
983+ self . state = . endOrError
968984 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
969985 }
970986 default :
971- self . state = . end
987+ self . state = . endOrError
972988 self . failTaskAndNotifyDelegate ( error: error, self . delegate. didReceiveError)
973989 }
974990 }
0 commit comments