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

caddyhttp: Added plaintext capability to file_server browse #6093

Merged
merged 9 commits into from
Apr 1, 2024
36 changes: 33 additions & 3 deletions modules/caddyhttp/fileserver/browse.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"path"
"strings"
"sync"
"text/tabwriter"
"text/template"

"go.uber.org/zap"
Expand Down Expand Up @@ -111,13 +112,42 @@ func (fsrv *FileServer) serveBrowse(fileSystem fs.FS, root, dirPath string, w ht

acceptHeader := strings.ToLower(strings.Join(r.Header["Accept"], ","))

// write response as either JSON or HTML
if strings.Contains(acceptHeader, "application/json") {
switch {
case strings.Contains(acceptHeader, "application/json"):
if err := json.NewEncoder(buf).Encode(listing.Items); err != nil {
return caddyhttp.Error(http.StatusInternalServerError, err)
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
} else {

case strings.Contains(acceptHeader, "text/plain"):
writer := tabwriter.NewWriter(buf, 0, 8, 1, '\t', tabwriter.AlignRight)

// Header on top
if _, err := fmt.Fprintln(writer, "Name\tSize\tModified"); err != nil {
return caddyhttp.Error(http.StatusInternalServerError, err)
}

// Lines to separate the header
if _, err := fmt.Fprintln(writer, "----\t----\t--------"); err != nil {
return caddyhttp.Error(http.StatusInternalServerError, err)
}

// Actual files
for _, item := range listing.Items {
if _, err := fmt.Fprintf(writer, "%s\t%s\t%s\n",
item.Name, item.HumanSize(), item.HumanModTime("January 2, 2006 at 15:04:05"),
); err != nil {
return caddyhttp.Error(http.StatusInternalServerError, err)
}
}

if err := writer.Flush(); err != nil {
return caddyhttp.Error(http.StatusInternalServerError, err)
}

w.Header().Set("Content-Type", "text/plain; charset=utf-8")

default:
var fs http.FileSystem
if fsrv.Root != "" {
fs = http.Dir(repl.ReplaceAll(fsrv.Root, "."))
Expand Down
12 changes: 7 additions & 5 deletions modules/caddyhttp/fileserver/caddyfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,15 @@ func (fsrv *FileServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
fsrv.Browse = new(Browse)
d.Args(&fsrv.Browse.TemplateFile)
for nesting := d.Nesting(); d.NextBlock(nesting); {
if d.Val() != "reveal_symlinks" {
switch d.Val() {
case "reveal_symlinks":
if fsrv.Browse.RevealSymlinks {
return d.Err("Symlinks path reveal is already enabled")
}
fsrv.Browse.RevealSymlinks = true
default:
return d.Errf("unknown subdirective '%s'", d.Val())
}
if fsrv.Browse.RevealSymlinks {
return d.Err("Symlinks path reveal is already enabled")
}
fsrv.Browse.RevealSymlinks = true
}

case "precompressed":
Expand Down
Loading