Description
I am using fasthttp as a proxy server which will call downstream service that return stream response, however when downstream request timeout before fully returned the stream response body will cause the next request fail to parse the response header due the reason that the clientconn
is being re-used and there are some data from previous request.
In the default transport RoundTrip()
, when we only use hc.releaseConn(cc)
in the resp.bodyStream
instead of closing the conn. For stream response, is it possible to close the tcp connection if it is timeout to prevent the dirty data from previous request? Maybe we could change the newCloseReader
's close function to check if the read is timeout or others issue to better cleanup the connection?
resp.bodyStream = newCloseReader(rbs, func() error {
hc.releaseReader(br)
if r, ok := rbs.(*requestStream); ok {
releaseRequestStream(r)
}
if closeConn || resp.ConnectionClose() {
hc.closeConn(cc)
} else {
hc.releaseConn(cc)
}
return nil
})
How to re-produce:
func main() {
var lbc = fasthttp.LBClient{
Clients: make([]fasthttp.BalancingClient, 0),
Timeout: 1 * time.Second,
}
downStreamAdd := "127.0.0.1:3000"
lbc.Clients = append(lbc.Clients, &fasthttp.HostClient{
Addr: downStreamAdd,
StreamResponseBody: true,
RetryIf: func(request *fasthttp.Request) bool {
return false
},
})
server := fasthttp.Server{
Handler: func(ctx *fasthttp.RequestCtx) {
err := lbc.Do(&ctx.Request, &ctx.Response)
fmt.Println(err)
},
}
if err := server.ListenAndServe("localhost:8080"); err != nil {
fmt.Println("fail to start server", err.Error())
}
}
- Create stream response service that return data more 1 second
- Make another request after timeout
- Receive error message failed to read response haeder
fail to make request: error when reading response headers: cannot find whitespace in the first line of response "2\r\n9\n\r\n3\r\n10\n\r\n3\r\n11\n\r\n3\r\n12\n\r\n3\r\n13\n\r\n3\r\n14\n\r\n3\r\n15\n\r\n3\r\n16\n\r\n3\r\n17\n\r\n3\r\n18\n\r\n3\r\n19\n\r\n3\r\n20\n\r\n3\r\n21\n\r\n3\r\n22\n\r\n3\r\n23\n\r\n3\r\n24\n\r\n3\r\n25\n\r\n3\r\n26\n\r\n3\r\n27\n\r\n3\r\n28\n\r\n0\r\n\r\n". Buffer size=164, contents: "2\r\n9\n\r\n3\r\n10\n\r\n3\r\n11\n\r\n3\r\n12\n\r\n3\r\n13\n\r\n3\r\n14\n\r\n3\r\n15\n\r\n3\r\n16\n\r\n3\r\n17\n\r\n3\r\n18\n\r\n3\r\n19\n\r\n3\r\n20\n\r\n3\r\n21\n\r\n3\r\n22\n\r\n3\r\n23\n\r\n3\r\n24\n\r\n3\r\n25\n\r\n3\r\n26\n\r\n3\r\n27\n\r\n3\r\n28\n\r\n0\r\n\r\n"
I tried a dirty hack to always close the clientconn
when cleaning up the response.bodyStream
but not sure if there is a better way of doing it and not really sure if this is a bug or I misuse it?