Skip to content

Timeout stream response connection does not clear buffer data for re-use #1743

Closed
@TAYTS

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())
	}
}
  1. Create stream response service that return data more 1 second
  2. Make another request after timeout
  3. 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?

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions