feat: implement io.ReaderFrom in wrapped response#73
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #73 +/- ##
=====================================
Coverage 0.00% 0.00%
=====================================
Files 4 4
Lines 365 372 +7
=====================================
- Misses 365 372 +7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds io.ReaderFrom support to the wrapped gin.ResponseWriter (bodyWriter) so io.Copy-style response writes can take the optimized ReadFrom path while still tracking response byte counts.
Changes:
- Assert
bodyWriterimplementsio.ReaderFrom. - Add
ReadFrom(io.Reader) (int64, error)implementation tobodyWriter.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return n, err | ||
| } | ||
| } | ||
| return io.Copy(w, r) |
There was a problem hiding this comment.
ReadFrom calls io.Copy(w, r) in the fallback path, but since bodyWriter now implements io.ReaderFrom, io.Copy will call ReadFrom again and recurse indefinitely (e.g., when w.body != nil or when the underlying ResponseWriter does not implement io.ReaderFrom). Implement the copy loop manually, or call io.Copy on a wrapper type that only exposes io.Writer to avoid the ReaderFrom fast-path.
| return io.Copy(w, r) | |
| var written int64 | |
| buf := make([]byte, 32*1024) | |
| for { | |
| nr, er := r.Read(buf) | |
| if nr > 0 { | |
| nw, ew := w.Write(buf[:nr]) | |
| if nw > 0 { | |
| written += int64(nw) | |
| } | |
| if ew != nil { | |
| return written, ew | |
| } | |
| if nw != nr { | |
| return written, io.ErrShortWrite | |
| } | |
| } | |
| if er != nil { | |
| if er == io.EOF { | |
| break | |
| } | |
| return written, er | |
| } | |
| } | |
| return written, nil |
| n, err := rf.ReadFrom(r) | ||
| w.bytes += int(n) | ||
| return n, err |
There was a problem hiding this comment.
w.bytes += int(n) converts the int64 byte count returned by ReadFrom to int, which can overflow on large responses (and silently wrap). Consider tracking byte counts as int64 throughout (bodyWriter.bytes, bodyReader.bytes) and logging with slog.Int64, or clamp the value before converting.
No description provided.