Skip to content

bi-directional streaming broken#327

@weissi

Description

@weissi

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

privatefunc writeBodyPart(context:ChannelHandlerContext, part:IOData, promise:EventLoopPromise<Void>){switchself.state {case.idle:iflet limit =self.expectedBodyLength,self.actualBodyLength + part.readableBytes > limit {leterror=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:leterror=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.

Metadata

Metadata

Assignees

Labels

kind/bugFeature doesn't work as expected.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions