From 33f60da9f2d6edc5de550275f043c4262d23f6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abdussamet=20Ko=C3=A7ak?= Date: Sat, 8 Oct 2022 21:56:35 +0300 Subject: fileserver: stop listing dir when request context is cancelled (#5131) Prevents caddy from performing disk IO needlessly when the request is cancelled before the listing is finished. Closes #5129 --- modules/caddyhttp/fileserver/browse.go | 7 ++++--- modules/caddyhttp/fileserver/browsetplcontext.go | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/caddyhttp/fileserver/browse.go b/modules/caddyhttp/fileserver/browse.go index 6a72e15..a8f5e8a 100644 --- a/modules/caddyhttp/fileserver/browse.go +++ b/modules/caddyhttp/fileserver/browse.go @@ -16,6 +16,7 @@ package fileserver import ( "bytes" + "context" _ "embed" "encoding/json" "fmt" @@ -82,7 +83,7 @@ func (fsrv *FileServer) serveBrowse(root, dirPath string, w http.ResponseWriter, repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) // calling path.Clean here prevents weird breadcrumbs when URL paths are sketchy like /%2e%2e%2f - listing, err := fsrv.loadDirectoryContents(dir.(fs.ReadDirFile), root, path.Clean(r.URL.Path), repl) + listing, err := fsrv.loadDirectoryContents(r.Context(), dir.(fs.ReadDirFile), root, path.Clean(r.URL.Path), repl) switch { case os.IsPermission(err): return caddyhttp.Error(http.StatusForbidden, err) @@ -136,7 +137,7 @@ func (fsrv *FileServer) serveBrowse(root, dirPath string, w http.ResponseWriter, return nil } -func (fsrv *FileServer) loadDirectoryContents(dir fs.ReadDirFile, root, urlPath string, repl *caddy.Replacer) (browseTemplateContext, error) { +func (fsrv *FileServer) loadDirectoryContents(ctx context.Context, dir fs.ReadDirFile, root, urlPath string, repl *caddy.Replacer) (browseTemplateContext, error) { files, err := dir.ReadDir(10000) // TODO: this limit should probably be configurable if err != nil && err != io.EOF { return browseTemplateContext{}, err @@ -145,7 +146,7 @@ func (fsrv *FileServer) loadDirectoryContents(dir fs.ReadDirFile, root, urlPath // user can presumably browse "up" to parent folder if path is longer than "/" canGoUp := len(urlPath) > 1 - return fsrv.directoryListing(files, canGoUp, root, urlPath, repl), nil + return fsrv.directoryListing(ctx, files, canGoUp, root, urlPath, repl), nil } // browseApplyQueryParams applies query parameters to the listing. diff --git a/modules/caddyhttp/fileserver/browsetplcontext.go b/modules/caddyhttp/fileserver/browsetplcontext.go index cd24fc2..172fa50 100644 --- a/modules/caddyhttp/fileserver/browsetplcontext.go +++ b/modules/caddyhttp/fileserver/browsetplcontext.go @@ -15,6 +15,7 @@ package fileserver import ( + "context" "io/fs" "net/url" "os" @@ -30,13 +31,17 @@ import ( "go.uber.org/zap" ) -func (fsrv *FileServer) directoryListing(entries []fs.DirEntry, canGoUp bool, root, urlPath string, repl *caddy.Replacer) browseTemplateContext { +func (fsrv *FileServer) directoryListing(ctx context.Context, entries []fs.DirEntry, canGoUp bool, root, urlPath string, repl *caddy.Replacer) browseTemplateContext { filesToHide := fsrv.transformHidePaths(repl) var dirCount, fileCount int fileInfos := []fileInfo{} for _, entry := range entries { + if err := ctx.Err(); err != nil { + break + } + name := entry.Name() if fileHidden(name, filesToHide) { -- cgit v1.2.3