Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support sendfile when echo is static file server #2725

Open
lp2jx0309 opened this issue Dec 23, 2024 · 4 comments
Open

support sendfile when echo is static file server #2725

lp2jx0309 opened this issue Dec 23, 2024 · 4 comments

Comments

@lp2jx0309
Copy link

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

@aldas
Copy link
Contributor

aldas commented Dec 23, 2024

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

@lp2jx0309
Copy link
Author

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
Copy link
Author

image

@aldas
Copy link
Contributor

aldas commented Dec 23, 2024

ok, I see. we are talking about this place in Echo

echo/middleware/static.go

Lines 243 to 246 in 45524e3

func serveFile(c echo.Context, file http.File, info os.FileInfo) error {
http.ServeContent(c.Response(), c.Request(), info.Name(), info.ModTime(), file)
return nil
}

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants