echo icon indicating copy to clipboard operation
echo copied to clipboard

support sendfile when echo is static file server

Open lp2jx0309 opened this issue 1 year ago • 4 comments

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

lp2jx0309 avatar Dec 23 '24 06:12 lp2jx0309

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)
	}
}

aldas avatar Dec 23 '24 07:12 aldas

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)
	}

lp2jx0309 avatar Dec 23 '24 07:12 lp2jx0309

image

lp2jx0309 avatar Dec 23 '24 07:12 lp2jx0309

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

aldas avatar Dec 23 '24 07:12 aldas