package browse import ( "fmt" "io/ioutil" "net/http" "text/template" "github.com/mholt/caddy" "github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/staticfiles" ) func init() { caddy.RegisterPlugin("browse", caddy.Plugin{ ServerType: "http", Action: setup, }) } // setup configures a new Browse middleware instance. func setup(c *caddy.Controller) error { configs, err := browseParse(c) if err != nil { return err } b := Browse{ Configs: configs, IgnoreIndexes: false, } httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { b.Next = next return b }) return nil } func browseParse(c *caddy.Controller) ([]Config, error) { var configs []Config cfg := httpserver.GetConfig(c) appendCfg := func(bc Config) error { for _, c := range configs { if c.PathScope == bc.PathScope { return fmt.Errorf("duplicate browsing config for %s", c.PathScope) } } configs = append(configs, bc) return nil } for c.Next() { var bc Config // First argument is directory to allow browsing; default is site root if c.NextArg() { bc.PathScope = c.Val() } else { bc.PathScope = "/" } bc.Fs = staticfiles.FileServer{ Root: http.Dir(cfg.Root), Hide: httpserver.GetConfig(c).HiddenFiles, } // Second argument would be the template file to use var tplText string if c.NextArg() { tplBytes, err := ioutil.ReadFile(c.Val()) if err != nil { return configs, err } tplText = string(tplBytes) } else { tplText = defaultTemplate } // Build the template tpl, err := template.New("listing").Parse(tplText) if err != nil { return configs, err } bc.Template = tpl // Save configuration err = appendCfg(bc) if err != nil { return configs, err } } return configs, nil } // The default template to use when serving up directory listings const defaultTemplate = ` {{html .Name}}

{{range $i, $crumb := .Breadcrumbs}}{{html $crumb.Text}}{{if ne $i 0}}/{{end}}{{end}}

{{.NumDirs}} director{{if eq 1 .NumDirs}}y{{else}}ies{{end}} {{.NumFiles}} file{{if ne 1 .NumFiles}}s{{end}} {{- if ne 0 .ItemsLimitedTo}} (of which only {{.ItemsLimitedTo}} are displayed) {{- end}}
{{- if .CanGoUp}} {{- end}} {{- range .Items}} {{- if .IsDir}} {{- else}} {{- end}} {{- end}}
{{- if and (eq .Sort "namedirfirst") (ne .Order "desc")}} {{- else if and (eq .Sort "namedirfirst") (ne .Order "asc")}} {{- else}} {{- end}} {{- if and (eq .Sort "name") (ne .Order "desc")}} Name {{- else if and (eq .Sort "name") (ne .Order "asc")}} Name {{- else}} Name {{- end}} {{- if and (eq .Sort "size") (ne .Order "desc")}} Size {{- else if and (eq .Sort "size") (ne .Order "asc")}} Size {{- else}} Size {{- end}} {{- if and (eq .Sort "time") (ne .Order "desc")}} Modified {{- else if and (eq .Sort "time") (ne .Order "asc")}} Modified {{- else}} Modified {{- end}}
Go up
{{- if .IsDir}} {{- else}} {{- end}} {{html .Name}} {{.HumanSize}}
`