diff --git a/context.go b/context.go index 1dc730e3..96f51e7e 100644 --- a/context.go +++ b/context.go @@ -1339,6 +1339,24 @@ func (c *Context) File(filepath string) { // FileFromFS writes the specified file from http.FileSystem into the body stream in an efficient way. func (c *Context) FileFromFS(filepath string, fs http.FileSystem) { + file, err := fs.Open(filepath) + if err != nil { + http.NotFound(c.Writer, c.Request) + return + } + defer file.Close() + + info, err := file.Stat() + if err != nil { + http.NotFound(c.Writer, c.Request) + return + } + + if !info.IsDir() { + http.ServeContent(c.Writer, c.Request, filepath, info.ModTime(), file) + return + } + defer func(old string) { c.Request.URL.Path = old }(c.Request.URL.Path) diff --git a/context_test.go b/context_test.go index e8d305e4..34f7032b 100644 --- a/context_test.go +++ b/context_test.go @@ -25,6 +25,7 @@ import ( "strings" "sync" "testing" + "testing/fstest" "time" "github.com/gin-contrib/sse" @@ -1558,6 +1559,21 @@ func TestContextRenderFileFromFS(t *testing.T) { assert.Equal(t, "/some/path", c.Request.URL.Path) } +func TestContextRenderFileFromFSIndexHTML(t *testing.T) { + w := httptest.NewRecorder() + c, _ := CreateTestContext(w) + + c.Request, _ = http.NewRequest(http.MethodGet, "/", nil) + c.FileFromFS("www/index.html", http.FS(fstest.MapFS{ + "www/index.html": {Data: []byte("index")}, + })) + + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "index", w.Body.String()) + assert.Empty(t, w.Header().Get("Location")) + assert.Equal(t, "/", c.Request.URL.Path) +} + func TestContextRenderAttachment(t *testing.T) { w := httptest.NewRecorder() c, _ := CreateTestContext(w)