Closed
Description
AsyncHTTPClient can no longer stream bi-directionally since commit f69b68f . When being bed the body, it throws a HTTPClientError.writeAfterRequestSent
.
The problem is this code
private func writeBodyPart(context: ChannelHandlerContext, part: IOData, promise: EventLoopPromise<Void>) {
switch self.state {
case .idle:
if let limit = self.expectedBodyLength, self.actualBodyLength + part.readableBytes > limit {
let error = HTTPClientError.bodyLengthMismatch
self.state = .endOrError
self.failTaskAndNotifyDelegate(error: error, self.delegate.didReceiveError)
promise.fail(error)
return
}
self.actualBodyLength += part.readableBytes
context.writeAndFlush(self.wrapOutboundOut(.body(part)), promise: promise)
default:
let error = HTTPClientError.writeAfterRequestSent
self.state = .endOrError
self.failTaskAndNotifyDelegate(error: error, self.delegate.didReceiveError)
promise.fail(error)
}
}
So we only accept bytes for the body in state .idle
but whilst streaming bi-directionally we can be in state .body
which makes AHC then wrongly reject the bytes.
Test case:
If you swift run
the repository at https://github.com/weissi/HTTPBidiStreamingExamples it will work.
If you however edit its Package.swift
and change
.package(url: "https://github.com/swift-server/async-http-client.git", .revision("2e6a64abb31fbc2d51da3919b0d8b35a6c7dc0b5")),
to
.package(url: "https://github.com/swift-server/async-http-client.git", from: "1.2.3")),
then it'll fail. How can I tell if it worked? If you grep for all the output lines that contain Final result
, what you should see is
2021-01-18T21:15:38+0000 info bidi-streaming.driver : driver=client: urlSession, server: swiftNIO Final result: ✅ OK
2021-01-18T21:15:38+0000 info bidi-streaming.driver : driver=client: asyncHTTPClient, server: swiftNIO Final result: ✅ OK
2021-01-18T21:15:38+0000 info bidi-streaming.driver : driver=client: urlSession, server: vapor Final result: ✅ OK
2021-01-18T21:15:38+0000 info bidi-streaming.driver : driver=client: asyncHTTPClient, server: vapor Final result: ✅ OK
but if you select the latest AHC, you'll see
2021-01-18T21:17:10+0000 info bidi-streaming.driver : driver=client: urlSession, server: swiftNIO Final result: ✅ OK
2021-01-18T21:17:10+0000 error bidi-streaming.driver : driver=client: asyncHTTPClient, server: swiftNIO Final result: ❌ ERROR: HTTPClientError.writeAfterRequestSent
2021-01-18T21:17:10+0000 info bidi-streaming.driver : driver=client: urlSession, server: vapor Final result: ✅ OK
2021-01-18T21:17:10+0000 error bidi-streaming.driver : driver=client: asyncHTTPClient, server: vapor Final result: ❌ ERROR: HTTPClientError.writeAfterRequestSent
As you can see: URLSession works and AHC fails against both NIO and Vapor.