Keep ServeContent on the sendfile path
This commit is contained in:
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user