Currently using HostClient.Do() will always read the whole request body before returning. Are there plans to add a way to stream partial body responses, similar to what can be done by reading Response.Body when using net/http?
This is specially useful for long lived connections that keep sending data over some time
Response body streaming is a nice feature, but currently I'm unsure with the API and the approach for implementing the feature.
Patches and API proposals are welcome.
Add Request body streaming also?
+1
@cezarsa See #150 , is it what you want? :)
@aspcartman Great work! I think that's one step on the right direction. But I have one question, this implementation would not handle chunked transfer encodings, right?
I think this may be a burden for some use cases as every user would have to manually parse the chunks. Did you consider adding the logic currently inside readBodyChunked to the Reader itself?
When I wrote this issue I thought about contributing this in the future but ended up without enough time. Thanks for working on this.
@cezarsa I'll take a look into this. I'm not familiar with chunked encoding yet. It would help to have a testable url with chunked response body. Do you have any? :)
I'm inclined to make a new special HostClient Do method (instead of manual accessor struct), which would take an boolean argument - chunked or not. Twitter's API response header says it's chunked, but I don't see any chunks in the stream, just a raw json bytes flowing.
@aspcartman Even better than a url with chunked response. Here is an example of a chunked response using net/http you can easily turn into a test case: https://play.golang.org/p/vbkvDEbq9o
As you can see I'm using net.Dial instead of http.Get because when using the http client directly the Reader returned in rsp.Body would already parse the chunks and you wouldn't be able to see them printed.
What's the current status of adding support for streaming request and response bodies with fasthttp?
After digging the source code, I found fasthttp support streaming request and response bodies.
// this only set a callback(sw), real streaming is done in sw(stream writing) and after RequestHandler() finished so fast http will write data
ctx.SetBodyStreamWriter(sw)
request.SetBodyStreamWriter(sw)
response.BodyWriteTo(ctx) // NOTE: This call will bock until streaming is over
@Jack47 yes, but for client does not exist any implementation of body reader. If you want to implement it I cheer you to do it in https://github.com/erikdubbelboer/fasthttp
@themester We can use pipe to let the client get body reader of response:
func BodyReadCloser(resp *fasthttp.Response) io.ReadCloser {
// fasthttputil.NewPipeConns uses memory buffer
// so it's faster than io.Pipe()
c := fasthttputil.NewPipeConns()
r := c.Conn1()
w := c.Conn2()
go func() {
_ = resp.BodyWriteTo(w) // ignore error safely
w.Close()
}()
return r
}
@Jack47
Hi, I'm not sure that I understand you correctly.
In my opinion, what we need is a resp with a io.readCloser to let the client have a chance to read the streaming body.
But now the Do(req, resp) call will block on chunked resp, how would we handle this?
@carlonelong I have discussed this in this comment on another issue. As you can see that issue is still open and my code will require some changes and cleanup to be possibly merged in the future.
Most helpful comment
What's the current status of adding support for streaming request and response bodies with fasthttp?