diff options
| author | Matt Holt <mholt@users.noreply.github.com> | 2019-08-21 11:28:03 -0600 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-21 11:28:03 -0600 | 
| commit | 0544f0266a11874efb305a46db762248e64bc62d (patch) | |
| tree | 3e75e6f59047bb967c52915e1e75aee6ad67c0ea /modules/caddyhttp/fileserver | |
| parent | 42f75a4ca94ef3fb5e15a74e5dc9ef8b4f1f0b39 (diff) | |
| parent | b2aa679c33f63ebec5bc1a21bca01f345dffebdd (diff) | |
Merge pull request #2699 from caddyserver/cfadapter
v2: Implement config adapters and WIP Caddyfile adapter
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{} {  | 
