Skip to content

Commit 895cc06

Browse files
committed
add fix on customClieent
1 parent e321f7c commit 895cc06

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

internal/perf/vegeta.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,43 @@ func (pt *PerfTest) loadTargets(filepath string) ([]vegeta.Target, error) {
278278
return targets, nil
279279
}
280280

281+
// limitBodyTransport wraps an http.RoundTripper and pre-limits response bodies.
282+
//
283+
// Vegeta v12 library reads maxBody bytes then drains the remainder with
284+
// io.Copy(io.Discard, r.Body). If the server resets the connection during
285+
// that drain, Vegeta records the result as failed (Code=0) even though a 200
286+
// OK was already received. The Python/vegeta-CLI binary (older) skips the
287+
// drain step and counts 200 as success immediately.
288+
//
289+
// By capping resp.Body at maxBytes here, the subsequent drain reads 0 bytes
290+
// and succeeds, so res.Code is set to the actual HTTP status, matching the
291+
// Python/CLI behavior: success = received 2xx status.
292+
type limitBodyTransport struct {
293+
base http.RoundTripper
294+
maxBytes int64
295+
}
296+
297+
func (t *limitBodyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
298+
resp, err := t.base.RoundTrip(req)
299+
if err != nil || resp == nil {
300+
return resp, err
301+
}
302+
if resp.Body != nil {
303+
resp.Body = &limitedReadCloser{
304+
Reader: io.LimitReader(resp.Body, t.maxBytes),
305+
Closer: resp.Body,
306+
}
307+
}
308+
return resp, nil
309+
}
310+
311+
// limitedReadCloser combines a limited Reader with the original Closer so
312+
// resp.Body.Close() still reaches the underlying TCP connection.
313+
type limitedReadCloser struct {
314+
io.Reader
315+
io.Closer
316+
}
317+
281318
// runVegetaAttack executes a Vegeta attack using the library.
282319
func (pt *PerfTest) runVegetaAttack(ctx context.Context, targets []vegeta.Target, qps int, duration time.Duration, outputFile string) (*vegeta.Metrics, error) {
283320
rate := vegeta.Rate{Freq: qps, Per: time.Second}
@@ -296,7 +333,7 @@ func (pt *PerfTest) runVegetaAttack(ctx context.Context, targets []vegeta.Target
296333
}
297334

298335
customClient := &http.Client{
299-
Transport: tr,
336+
Transport: &limitBodyTransport{base: tr, maxBytes: int64(maxBodyInt)},
300337
}
301338

302339
//

0 commit comments

Comments
 (0)