Skip to content

Commit

Permalink
fileserver: stop listing dir when request context is cancelled
Browse files Browse the repository at this point in the history
Prevents caddy from performing disk IO needlessly when the request is cancelled before the listing is finished.

Closes caddyserver#5129
  • Loading branch information
abdusco committed Oct 8, 2022
1 parent b4e28af commit aa2c98c
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
7 changes: 4 additions & 3 deletions modules/caddyhttp/fileserver/browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package fileserver

import (
"bytes"
"context"
_ "embed"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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.
Expand Down
9 changes: 7 additions & 2 deletions modules/caddyhttp/fileserver/browsetplcontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package fileserver

import (
"context"
"io/fs"
"net/url"
"os"
Expand All @@ -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{}
var fileInfos []fileInfo

for _, entry := range entries {
if err := ctx.Err(); err != nil {
break
}

name := entry.Name()

if fileHidden(name, filesToHide) {
Expand Down

0 comments on commit aa2c98c

Please sign in to comment.