mirror of
https://github.com/valyala/fasthttp.git
synced 2026-06-13 15:46:49 +03:00
fix(client): avoid dst aliasing after timeout
This commit is contained in:
@@ -1093,9 +1093,10 @@ func clientGetURLDeadline(dst []byte, url string, deadline time.Time, c clientDo
|
||||
go func() {
|
||||
req := AcquireRequest()
|
||||
|
||||
statusCodeCopy, bodyCopy, errCopy := doRequestFollowRedirectsBuffer(req, dst, url, c)
|
||||
statusCodeCopy, bodyCopy, errCopy := doRequestFollowRedirectsBuffer(req, nil, url, c)
|
||||
mu.Lock()
|
||||
if !timedout {
|
||||
bodyCopy = append(dst[:0], bodyCopy...)
|
||||
ch <- clientURLResponse{
|
||||
statusCode: statusCodeCopy,
|
||||
body: bodyCopy,
|
||||
|
||||
@@ -2290,6 +2290,56 @@ func TestClientGetTimeoutError(t *testing.T) {
|
||||
testClientGetTimeoutError(t, c, 100)
|
||||
}
|
||||
|
||||
func TestClientGetURLDeadlineDoesNotMutateDstAfterTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
d := &delayedBodyDoer{
|
||||
unblock: make(chan struct{}),
|
||||
done: make(chan struct{}),
|
||||
body: "mutated!",
|
||||
}
|
||||
dst := []byte("original")
|
||||
|
||||
statusCode, body, err := clientGetURLDeadline(dst, "http://example.com/", time.Now().Add(time.Millisecond), d)
|
||||
if err != ErrTimeout {
|
||||
t.Fatalf("unexpected error: %v. Expecting %v", err, ErrTimeout)
|
||||
}
|
||||
if statusCode != 0 {
|
||||
t.Fatalf("unexpected status code: %d. Expecting 0", statusCode)
|
||||
}
|
||||
if string(body) != "original" {
|
||||
t.Fatalf("unexpected timeout body %q. Expecting %q", body, "original")
|
||||
}
|
||||
|
||||
close(d.unblock)
|
||||
select {
|
||||
case <-d.done:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("timed out waiting for background request to finish")
|
||||
}
|
||||
|
||||
if string(dst) != "original" {
|
||||
t.Fatalf("dst was mutated after timeout: %q. Expecting %q", dst, "original")
|
||||
}
|
||||
if string(body) != "original" {
|
||||
t.Fatalf("returned body was mutated after timeout: %q. Expecting %q", body, "original")
|
||||
}
|
||||
}
|
||||
|
||||
type delayedBodyDoer struct {
|
||||
unblock chan struct{}
|
||||
done chan struct{}
|
||||
body string
|
||||
}
|
||||
|
||||
func (d *delayedBodyDoer) Do(req *Request, resp *Response) error {
|
||||
<-d.unblock
|
||||
resp.SetStatusCode(StatusOK)
|
||||
resp.SetBodyString(d.body)
|
||||
close(d.done)
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestClientGetTimeoutErrorConcurrent(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user