support sendfile when echo is static file server
Issue Description
Response should implement io.ReaderFrom interface, only when used as a static file server can the sendfile function be used
Working code to debug
// ReadFrom is here to optimize copying from an [*os.File] regular file
// to a [*net.TCPConn] with sendfile, or from a supported src type such
// as a *net.TCPConn on Linux with splice.
func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
Version/commit
c.Response().Writer does not help?
you can verify this with
package main
import (
"errors"
"github.com/labstack/echo/v4"
"io"
"log/slog"
"net/http"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
_, ok := c.Response().Writer.(io.ReaderFrom)
if ok {
return c.JSON(http.StatusOK, "implements io.ReaderFrom")
}
return c.JSON(http.StatusOK, "nope")
})
if err := e.Start(":8080"); err != nil && !errors.Is(err, http.ErrServerClosed) {
slog.Error("failed to start server", "error", err)
}
}
http. ResponseWriter implements io ReaderFrom interface, so go SDK can support sendfile, but echo.Response not implemented, you can debug the code to see if the io.CpyBuffer method line cannot be converted, thus unable to use sendfile
// copyBuffer is the actual implementation of Copy and CopyBuffer.
// if buf is nil, one is allocated.
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
// If the reader has a WriteTo method, use it to do the copy.
// Avoids an allocation and a copy.
if wt, ok := src.(WriterTo); ok {
return wt.WriteTo(dst)
}
// Similarly, if the writer has a ReadFrom method, use it to do the copy.
if rt, ok := dst.(ReaderFrom); ok {
return rt.ReadFrom(src)
}
ok, I see. we are talking about this place in Echo https://github.com/labstack/echo/blob/45524e39d60d424d8ac175001eed70d6ace92930/middleware/static.go#L243-L246
maybe changing from
http.ServeContent(c.Response(), c.Request(), info.Name(), info.ModTime(), file)
to
http.ServeContent(c.Response().Writer, c.Request(), info.Name(), info.ModTime(), file)
would be enough