diff options
Diffstat (limited to 'modules/caddyhttp/fileserver')
-rw-r--r-- | modules/caddyhttp/fileserver/caddyfile.go | 104 | ||||
-rw-r--r-- | modules/caddyhttp/fileserver/matcher.go | 52 | ||||
-rw-r--r-- | modules/caddyhttp/fileserver/staticfiles.go | 17 |
3 files changed, 161 insertions, 12 deletions
diff --git a/modules/caddyhttp/fileserver/caddyfile.go b/modules/caddyhttp/fileserver/caddyfile.go new file mode 100644 index 0000000..6fa94e7 --- /dev/null +++ b/modules/caddyhttp/fileserver/caddyfile.go @@ -0,0 +1,104 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fileserver + +import ( + "encoding/json" + + "github.com/caddyserver/caddy/modules/caddyhttp/rewrite" + "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" + "github.com/caddyserver/caddy/v2/modules/caddyhttp" +) + +func init() { + httpcaddyfile.RegisterHandlerDirective("file_server", parseCaddyfile) + httpcaddyfile.RegisterDirective("try_files", parseTryFiles) +} + +func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) { + var fsrv FileServer + + for h.Next() { + args := h.RemainingArgs() + switch len(args) { + case 0: + case 1: + if args[0] != "browse" { + return nil, h.ArgErr() + } + fsrv.Browse = new(Browse) + default: + return nil, h.ArgErr() + } + + for h.NextBlock() { + switch h.Val() { + case "hide": + fsrv.Hide = h.RemainingArgs() + if len(fsrv.Hide) == 0 { + return nil, h.ArgErr() + } + case "index": + fsrv.IndexNames = h.RemainingArgs() + if len(fsrv.Hide) == 0 { + return nil, h.ArgErr() + } + case "root": + if !h.Args(&fsrv.Root) { + return nil, h.ArgErr() + } + case "browse": + if fsrv.Browse != nil { + return nil, h.Err("browsing is already configured") + } + fsrv.Browse = new(Browse) + h.Args(&fsrv.Browse.TemplateFile) + default: + return nil, h.Errf("unknown subdirective '%s'", h.Val()) + } + } + } + + // if no root was configured explicitly, use site root + if fsrv.Root == "" { + fsrv.Root = "{http.var.root}" + } + + return &fsrv, nil +} + +func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) { + if !h.Next() { + return nil, h.ArgErr() + } + + try := h.RemainingArgs() + if len(try) == 0 { + return nil, h.ArgErr() + } + + handler := rewrite.Rewrite{ + URI: "{http.matchers.file.relative}{http.request.uri.query}", + } + + matcherSet := map[string]json.RawMessage{ + "file": h.JSON(MatchFile{ + Root: "{http.var.root}", + TryFiles: try, + }, nil), + } + + return h.NewRoute(matcherSet, handler), nil +} diff --git a/modules/caddyhttp/fileserver/matcher.go b/modules/caddyhttp/fileserver/matcher.go index 17d5c11..b091250 100644 --- a/modules/caddyhttp/fileserver/matcher.go +++ b/modules/caddyhttp/fileserver/matcher.go @@ -21,14 +21,12 @@ import ( "time" "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp" ) func init() { - caddy.RegisterModule(caddy.Module{ - Name: "http.matchers.file", - New: func() interface{} { return new(MatchFile) }, - }) + caddy.RegisterModule(MatchFile{}) } // MatchFile is an HTTP request matcher that can match @@ -51,6 +49,50 @@ type MatchFile struct { TryPolicy string `json:"try_policy,omitempty"` } +// CaddyModule returns the Caddy module information. +func (MatchFile) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "http.matchers.file", + New: func() caddy.Module { return new(MatchFile) }, + } +} + +// UnmarshalCaddyfile sets up the matcher from Caddyfile tokens. Syntax: +// +// file { +// root <path> +// try_files <files...> +// try_policy first_exist|smallest_size|largest_size|most_recent_modified +// } +// +func (m *MatchFile) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { + for d.Next() { + for d.NextBlock() { + switch d.Val() { + case "root": + if !d.NextArg() { + return d.ArgErr() + } + m.Root = d.Val() + case "try_files": + m.TryFiles = d.RemainingArgs() + if len(m.TryFiles) == 0 { + return d.ArgErr() + } + case "try_policy": + if !d.NextArg() { + return d.ArgErr() + } + m.TryPolicy = d.Val() + } + } + } + if m.Root == "" { + m.Root = "{http.var.root}" + } + return nil +} + // Validate ensures m has a valid configuration. func (m MatchFile) Validate() error { switch m.TryPolicy { @@ -87,7 +129,7 @@ func (m MatchFile) Match(r *http.Request) bool { func (m MatchFile) selectFile(r *http.Request) (rel, abs string, matched bool) { repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer) - root := repl.ReplaceAll(m.Root, "") + root := repl.ReplaceAll(m.Root, ".") // if list of files to try was omitted entirely, // assume URL path diff --git a/modules/caddyhttp/fileserver/staticfiles.go b/modules/caddyhttp/fileserver/staticfiles.go index a66b753..cdac453 100644 --- a/modules/caddyhttp/fileserver/staticfiles.go +++ b/modules/caddyhttp/fileserver/staticfiles.go @@ -36,10 +36,7 @@ import ( func init() { weakrand.Seed(time.Now().UnixNano()) - caddy.RegisterModule(caddy.Module{ - Name: "http.handlers.file_server", - New: func() interface{} { return new(FileServer) }, - }) + caddy.RegisterModule(FileServer{}) } // FileServer implements a static file server responder for Caddy. @@ -48,8 +45,14 @@ type FileServer struct { Hide []string `json:"hide,omitempty"` IndexNames []string `json:"index_names,omitempty"` Browse *Browse `json:"browse,omitempty"` +} - // TODO: Content negotiation +// CaddyModule returns the Caddy module information. +func (FileServer) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "http.handlers.file_server", + New: func() caddy.Module { return new(FileServer) }, + } } // Provision sets up the static files responder. @@ -83,7 +86,7 @@ func (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, _ cadd filesToHide := fsrv.transformHidePaths(repl) - root := repl.ReplaceAll(fsrv.Root, "") + root := repl.ReplaceAll(fsrv.Root, ".") suffix := repl.ReplaceAll(r.URL.Path, "") filename := sanitizedPathJoin(root, suffix) @@ -302,7 +305,7 @@ func calculateEtag(d os.FileInfo) string { return `"` + t + s + `"` } -var defaultIndexNames = []string{"index.html"} +var defaultIndexNames = []string{"index.html", "index.txt"} var bufPool = sync.Pool{ New: func() interface{} { |