From 94ae667fa10a19a6598348db87022a75bd5b34e2 Mon Sep 17 00:00:00 2001 From: Atakan Yenel Date: Sun, 20 Oct 2024 21:25:52 +0000 Subject: [PATCH 1/3] Add file_limit option for file_server browse --- modules/caddyhttp/fileserver/browse.go | 13 ++++++++++++- modules/caddyhttp/fileserver/caddyfile.go | 13 +++++++++++++ modules/caddyhttp/fileserver/command.go | 4 +++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/modules/caddyhttp/fileserver/browse.go b/modules/caddyhttp/fileserver/browse.go index a19b4e17a85..badb6b91a86 100644 --- a/modules/caddyhttp/fileserver/browse.go +++ b/modules/caddyhttp/fileserver/browse.go @@ -66,8 +66,15 @@ type Browse struct { // - `sort size` will sort by size in ascending order // The first option must be `sort_by` and the second option must be `order` (if exists). SortOptions []string `json:"sort,omitempty"` + + // FileLimit limits the number of up to n DirEntry values in directory order. + FileLimit int `json:"file_limit,omitempty"` } +const ( + defaultMaxDirLimit = 10000 +) + func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { if c := fsrv.logger.Check(zapcore.DebugLevel, "browse enabled; listing directory contents"); c != nil { c.Write(zap.String("path", dirPath), zap.String("root", root)) @@ -206,7 +213,11 @@ func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w ht } func (fsrv *FileServer) loadDirectoryContents(ctx context.Context, fileSystem fs.FS, dir fs.ReadDirFile, root, urlPath string, repl *caddy.Replacer) (*browseTemplateContext, error) { - files, err := dir.ReadDir(10000) // TODO: this limit should probably be configurable + dirLimit := defaultMaxDirLimit + if fsrv.Browse.FileLimit != 0 { + dirLimit = fsrv.Browse.FileLimit + } + files, err := dir.ReadDir(dirLimit) if err != nil && err != io.EOF { return nil, err } diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go index 71b7638e477..73fe8ae55b1 100644 --- a/modules/caddyhttp/fileserver/caddyfile.go +++ b/modules/caddyhttp/fileserver/caddyfile.go @@ -16,6 +16,7 @@ package fileserver import ( "path/filepath" + "strconv" "strings" "github.com/caddyserver/caddy/v2" @@ -58,6 +59,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) // browse [] // precompressed // status +// file_limit // disable_canonical_uris // } // @@ -168,6 +170,17 @@ func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { falseBool := false fsrv.CanonicalURIs = &falseBool + case "file_limit": + fileLimit := d.RemainingArgs() + if len(fileLimit) != 1 { + return d.Err("file_limit should have an integer value") + } + val, _ := strconv.Atoi(fileLimit[0]) + if fsrv.Browse.FileLimit != 0 { + return d.Err("file_limit is already enabled") + } + fsrv.Browse.FileLimit = val + case "pass_thru": if d.NextArg() { return d.ArgErr() diff --git a/modules/caddyhttp/fileserver/command.go b/modules/caddyhttp/fileserver/command.go index a76998405d3..8b03d855dac 100644 --- a/modules/caddyhttp/fileserver/command.go +++ b/modules/caddyhttp/fileserver/command.go @@ -66,6 +66,7 @@ respond with a file listing.`, cmd.Flags().BoolP("templates", "t", false, "Enable template rendering") cmd.Flags().BoolP("access-log", "a", false, "Enable the access log") cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs") + cmd.Flags().IntP("file-limit", "f", defaultMaxDirLimit, "Max directories to read") cmd.Flags().BoolP("no-compress", "", false, "Disable Zstandard and Gzip compression") cmd.Flags().StringSliceP("precompressed", "p", []string{}, "Specify precompression file extensions. Compression preference implied from flag order.") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdFileServer) @@ -91,6 +92,7 @@ func cmdFileServer(fs caddycmd.Flags) (int, error) { browse := fs.Bool("browse") templates := fs.Bool("templates") accessLog := fs.Bool("access-log") + fileLimit := fs.Int("file-limit") debug := fs.Bool("debug") revealSymlinks := fs.Bool("reveal-symlinks") compress := !fs.Bool("no-compress") @@ -151,7 +153,7 @@ func cmdFileServer(fs caddycmd.Flags) (int, error) { } if browse { - handler.Browse = &Browse{RevealSymlinks: revealSymlinks} + handler.Browse = &Browse{RevealSymlinks: revealSymlinks, FileLimit: fileLimit} } handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "file_server", nil)) From 93c3ae322c31252849d8ae8dd83f6760e8e11695 Mon Sep 17 00:00:00 2001 From: Atakan Yenel Date: Tue, 22 Oct 2024 16:59:10 +0000 Subject: [PATCH 2/3] Move file_limit inside browse. --- modules/caddyhttp/fileserver/caddyfile.go | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go index 73fe8ae55b1..689f27e8ccf 100644 --- a/modules/caddyhttp/fileserver/caddyfile.go +++ b/modules/caddyhttp/fileserver/caddyfile.go @@ -59,7 +59,6 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) // browse [] // precompressed // status -// file_limit // disable_canonical_uris // } // @@ -131,6 +130,16 @@ func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return d.Errf("unknown sort option '%s'", dVal) } } + case "file_limit": + fileLimit := d.RemainingArgs() + if len(fileLimit) != 1 { + return d.Err("file_limit should have an integer value") + } + val, _ := strconv.Atoi(fileLimit[0]) + if fsrv.Browse.FileLimit != 0 { + return d.Err("file_limit is already enabled") + } + fsrv.Browse.FileLimit = val default: return d.Errf("unknown subdirective '%s'", d.Val()) } @@ -170,17 +179,6 @@ func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { falseBool := false fsrv.CanonicalURIs = &falseBool - case "file_limit": - fileLimit := d.RemainingArgs() - if len(fileLimit) != 1 { - return d.Err("file_limit should have an integer value") - } - val, _ := strconv.Atoi(fileLimit[0]) - if fsrv.Browse.FileLimit != 0 { - return d.Err("file_limit is already enabled") - } - fsrv.Browse.FileLimit = val - case "pass_thru": if d.NextArg() { return d.ArgErr() From 555c335158172a5282a9fd76c19c06649a27d9a8 Mon Sep 17 00:00:00 2001 From: Atakan Yenel Date: Tue, 22 Oct 2024 18:46:11 +0000 Subject: [PATCH 3/3] add file_server_file_limit caddyfile adapt test. --- .../file_server_file_limit.caddyfiletest | 36 +++++++++++++++++++ modules/caddyhttp/fileserver/browse.go | 4 +-- modules/caddyhttp/fileserver/command.go | 2 +- 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 caddytest/integration/caddyfile_adapt/file_server_file_limit.caddyfiletest diff --git a/caddytest/integration/caddyfile_adapt/file_server_file_limit.caddyfiletest b/caddytest/integration/caddyfile_adapt/file_server_file_limit.caddyfiletest new file mode 100644 index 00000000000..cd73fbff684 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/file_server_file_limit.caddyfiletest @@ -0,0 +1,36 @@ +:80 + +file_server { + browse { + file_limit 4000 + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "handle": [ + { + "browse": { + "file_limit": 4000 + }, + "handler": "file_server", + "hide": [ + "./Caddyfile" + ] + } + ] + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/modules/caddyhttp/fileserver/browse.go b/modules/caddyhttp/fileserver/browse.go index badb6b91a86..0a623c79eb7 100644 --- a/modules/caddyhttp/fileserver/browse.go +++ b/modules/caddyhttp/fileserver/browse.go @@ -72,7 +72,7 @@ type Browse struct { } const ( - defaultMaxDirLimit = 10000 + defaultDirEntryLimit = 10000 ) func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error { @@ -213,7 +213,7 @@ func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w ht } func (fsrv *FileServer) loadDirectoryContents(ctx context.Context, fileSystem fs.FS, dir fs.ReadDirFile, root, urlPath string, repl *caddy.Replacer) (*browseTemplateContext, error) { - dirLimit := defaultMaxDirLimit + dirLimit := defaultDirEntryLimit if fsrv.Browse.FileLimit != 0 { dirLimit = fsrv.Browse.FileLimit } diff --git a/modules/caddyhttp/fileserver/command.go b/modules/caddyhttp/fileserver/command.go index 8b03d855dac..a04d7cade07 100644 --- a/modules/caddyhttp/fileserver/command.go +++ b/modules/caddyhttp/fileserver/command.go @@ -66,7 +66,7 @@ respond with a file listing.`, cmd.Flags().BoolP("templates", "t", false, "Enable template rendering") cmd.Flags().BoolP("access-log", "a", false, "Enable the access log") cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs") - cmd.Flags().IntP("file-limit", "f", defaultMaxDirLimit, "Max directories to read") + cmd.Flags().IntP("file-limit", "f", defaultDirEntryLimit, "Max directories to read") cmd.Flags().BoolP("no-compress", "", false, "Disable Zstandard and Gzip compression") cmd.Flags().StringSliceP("precompressed", "p", []string{}, "Specify precompression file extensions. Compression preference implied from flag order.") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdFileServer)