From cf1c2844bfc061b573dbced7f156451c57075ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 8 Sep 2026 20:11:06 +0200 Subject: [PATCH] Keep ServeContent on the sendfile path --- main.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/main.go b/main.go index b59cdd4..2b80b50 100644 --- a/main.go +++ b/main.go @@ -632,6 +632,29 @@ func (rr *responseRecorder) Write(b []byte) (int, error) { return n, err } +// ReadFrom keeps downloads on the kernel's sendfile path. io.Copy — which is +// where http.ServeContent ends up — only lets the destination take over the +// copy when it implements io.ReaderFrom, so wrapping the ResponseWriter would +// otherwise hide net/http's own implementation and push every byte through a +// userspace buffer. +func (rr *responseRecorder) ReadFrom(src io.Reader) (int64, error) { + if rr.status == 0 { + rr.status = http.StatusOK + } + + var n int64 + var err error + if rf, ok := rr.ResponseWriter.(io.ReaderFrom); ok { + n, err = rf.ReadFrom(src) + } else { + // Copy into the wrapped writer, not into rr, or this recurses. + n, err = io.Copy(rr.ResponseWriter, src) + } + + rr.written += n + return n, err +} + // Unwrap lets http.ResponseController and baseWriter reach the original // ResponseWriter. func (rr *responseRecorder) Unwrap() http.ResponseWriter { return rr.ResponseWriter }