Cannot read twice a response body when backed by Netty
Describe the bug When provided with the default Client, the following effect fails with an "IllegalStateException: Cannot connect twice":
val requestBodyAsChunk: RIO[Client, Chunk[Byte]] = ZIO.scoped {
for {
client <- ZIO.service[Client]
response <- client(Request.get("http://jsonplaceholder.typicode.com/todos"))
_ <- response.body.asChunk
bodyAsChunk <- response.body.asChunk
} yield bodyAsChunk
}
This is due to the zio.http.netty.AsyncBodyReader.connect method being called twice, the second time with an illegal state.
To Reproduce Run this Scastie
Expected behaviour
The fact that the response body uses zio.http.netty.AsyncBodyReader should be an implementation detail, and calling zio.http.Body.asChunk should not be stateful.
@kyri-petrou I think would could for the aggregation operations (asChunk/asArray) in the netty body cache the result internally? But I don't think we can do this for streaming, since it would defy the purpose of streaming it (not keeping all in memory). wdyt?
@987Nabil that's one option. Not exactly a fix, but this can also be achieved by using the batched API. The following works as expected:
val requestBodyAsChunk: RIO[Client, Chunk[Byte]] = {
for {
client <- ZIO.service[Client]
response <- client.batched(Request.get("http://jsonplaceholder.typicode.com/todos"))
_ <- response.body.asChunk
bodyAsChunk <- response.body.asChunk
} yield bodyAsChunk
}
You have to use the batched API if you want to read the body twice. I don't think we can fix this.