From ba29f9d41d7951bde07dc2e0d6a1471c40bb7145 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 19 Sep 2019 12:42:36 -0600 Subject: [PATCH] httpcaddyfile: Global storage configuration (closes #2758) --- caddyconfig/httpcaddyfile/httptype.go | 14 +++++--- caddyconfig/httpcaddyfile/options.go | 38 ++++++++++++++++++--- cmd/caddy/main.go | 1 + go.mod | 2 +- go.sum | 8 ++--- modules/caddyhttp/encode/caddyfile.go | 2 +- modules/filestorage/filestorage.go | 49 +++++++++++++++++++++++++++ storage.go | 24 ------------- 8 files changed, 98 insertions(+), 40 deletions(-) create mode 100644 modules/filestorage/filestorage.go diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 6b2ee6b8..ff340de8 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -57,15 +57,18 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, dir := segment.Directive() var val interface{} var err error + disp := caddyfile.NewDispenser(segment) switch dir { case "http_port": - val, err = parseHTTPPort(caddyfile.NewDispenser(segment)) + val, err = parseOptHTTPPort(disp) case "https_port": - val, err = parseHTTPSPort(caddyfile.NewDispenser(segment)) + val, err = parseOptHTTPSPort(disp) case "handler_order": - val, err = parseHandlerOrder(caddyfile.NewDispenser(segment)) + val, err = parseOptHandlerOrder(disp) case "experimental_http3": - val, err = parseExperimentalHTTP3(caddyfile.NewDispenser(segment)) + val, err = parseOptExperimentalHTTP3(disp) + case "storage": + val, err = parseOptStorage(disp) default: return nil, warnings, fmt.Errorf("unrecognized parameter name: %s", dir) } @@ -207,6 +210,9 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, if !reflect.DeepEqual(tlsApp, caddytls.TLS{}) { cfg.AppsRaw["tls"] = caddyconfig.JSON(tlsApp, &warnings) } + if storageCvtr, ok := options["storage"].(caddy.StorageConverter); ok { + cfg.StorageRaw = caddyconfig.JSON(storageCvtr, &warnings) + } return cfg, warnings, nil } diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go index 1d7864c3..dadde288 100644 --- a/caddyconfig/httpcaddyfile/options.go +++ b/caddyconfig/httpcaddyfile/options.go @@ -15,12 +15,14 @@ package httpcaddyfile import ( + "fmt" "strconv" + "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) -func parseHTTPPort(d *caddyfile.Dispenser) (int, error) { +func parseOptHTTPPort(d *caddyfile.Dispenser) (int, error) { var httpPort int for d.Next() { var httpPortStr string @@ -36,7 +38,7 @@ func parseHTTPPort(d *caddyfile.Dispenser) (int, error) { return httpPort, nil } -func parseHTTPSPort(d *caddyfile.Dispenser) (int, error) { +func parseOptHTTPSPort(d *caddyfile.Dispenser) (int, error) { var httpsPort int for d.Next() { var httpsPortStr string @@ -52,11 +54,11 @@ func parseHTTPSPort(d *caddyfile.Dispenser) (int, error) { return httpsPort, nil } -func parseExperimentalHTTP3(d *caddyfile.Dispenser) (bool, error) { +func parseOptExperimentalHTTP3(d *caddyfile.Dispenser) (bool, error) { return true, nil } -func parseHandlerOrder(d *caddyfile.Dispenser) ([]string, error) { +func parseOptHandlerOrder(d *caddyfile.Dispenser) ([]string, error) { if !d.Next() { return nil, d.ArgErr() } @@ -78,3 +80,31 @@ func parseHandlerOrder(d *caddyfile.Dispenser) ([]string, error) { } return order, nil } + +func parseOptStorage(d *caddyfile.Dispenser) (caddy.StorageConverter, error) { + if !d.Next() { + return nil, d.ArgErr() + } + args := d.RemainingArgs() + if len(args) != 1 { + return nil, d.ArgErr() + } + modName := args[0] + mod, err := caddy.GetModule("caddy.storage." + modName) + if err != nil { + return nil, fmt.Errorf("getting storage module '%s': %v", modName, err) + } + unm, ok := mod.New().(caddyfile.Unmarshaler) + if !ok { + return nil, fmt.Errorf("storage module '%s' is not a Caddyfile unmarshaler", mod.Name) + } + err = unm.UnmarshalCaddyfile(d.NewFromNextTokens()) + if err != nil { + return nil, err + } + storage, ok := unm.(caddy.StorageConverter) + if !ok { + return nil, fmt.Errorf("module %s is not a StorageConverter", mod.Name) + } + return storage, nil +} diff --git a/cmd/caddy/main.go b/cmd/caddy/main.go index 14b88658..9f548e38 100644 --- a/cmd/caddy/main.go +++ b/cmd/caddy/main.go @@ -34,6 +34,7 @@ import ( _ "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates" _ "github.com/caddyserver/caddy/v2/modules/caddytls" _ "github.com/caddyserver/caddy/v2/modules/caddytls/standardstek" + _ "github.com/caddyserver/caddy/v2/modules/filestorage" ) func main() { diff --git a/go.mod b/go.mod index 36457f42..c1c0fcbe 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/goutils v1.1.0 // indirect github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.20.0+incompatible - github.com/andybalholm/brotli v0.0.0-20190704151324-71eb68cc467c + github.com/andybalholm/brotli v0.0.0-20190821151343-b60f0d972eeb github.com/dustin/go-humanize v1.0.0 github.com/go-acme/lego/v3 v3.0.2 github.com/google/go-cmp v0.3.1 // indirect diff --git a/go.sum b/go.sum index 77d3eaf6..900b49e1 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/andybalholm/brotli v0.0.0-20190704151324-71eb68cc467c h1:pBKtfXLqKZ+GPHGjlBheGaXK2lddydUG3XhWGrYjxOA= -github.com/andybalholm/brotli v0.0.0-20190704151324-71eb68cc467c/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U= +github.com/andybalholm/brotli v0.0.0-20190821151343-b60f0d972eeb h1:ZSlUsEd11C/uRzhZHOgANARJ03fkwmjJEa6g2Cqjlo4= +github.com/andybalholm/brotli v0.0.0-20190821151343-b60f0d972eeb/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/aws/aws-sdk-go v1.23.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc= @@ -78,8 +78,6 @@ github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= -github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721 h1:KRMr9A3qfbVM7iV/WcLY/rL5LICqwMHLhwRXKu99fXw= -github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= @@ -158,8 +156,6 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mholt/certmagic v0.7.2 h1:i4FRZyM33Ke6UdTrq69hLSRq1xvqS83JQTkzzUWtuF4= -github.com/mholt/certmagic v0.7.2/go.mod h1:hqHzDsY32TwZpj/KswVylheSISjquF/eOVOaJTYV15w= github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI= github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= diff --git a/modules/caddyhttp/encode/caddyfile.go b/modules/caddyhttp/encode/caddyfile.go index 2f0e1512..4764e9b9 100644 --- a/modules/caddyhttp/encode/caddyfile.go +++ b/modules/caddyhttp/encode/caddyfile.go @@ -68,7 +68,7 @@ func (enc *Encode) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { name := d.Val() mod, err := caddy.GetModule("http.encoders." + name) if err != nil { - return fmt.Errorf("getting encoder module '%s': %v", mod.Name, err) + return fmt.Errorf("getting encoder module '%s': %v", name, err) } unm, ok := mod.New().(caddyfile.Unmarshaler) if !ok { diff --git a/modules/filestorage/filestorage.go b/modules/filestorage/filestorage.go new file mode 100644 index 00000000..654dbb24 --- /dev/null +++ b/modules/filestorage/filestorage.go @@ -0,0 +1,49 @@ +package filestorage + +import ( + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/certmagic" +) + +func init() { + caddy.RegisterModule(FileStorage{}) +} + +// FileStorage is a certmagic.Storage wrapper for certmagic.FileStorage. +type FileStorage struct { + Root string `json:"root,omitempty"` +} + +// CaddyModule returns the Caddy module information. +func (FileStorage) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + Name: "caddy.storage.file_system", + New: func() caddy.Module { return new(FileStorage) }, + } +} + +// CertMagicStorage converts s to a certmagic.Storage instance. +func (s FileStorage) CertMagicStorage() (certmagic.Storage, error) { + return &certmagic.FileStorage{Path: s.Root}, nil +} + +// UnmarshalCaddyfile sets up the storage module from Caddyfile tokens. +func (s *FileStorage) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { + if !d.Next() { + return d.Err("expected tokens") + } + for nesting := d.Nesting(); d.NextBlock(nesting); { + if !d.NextArg() { + return d.ArgErr() + } + s.Root = d.Val() + if d.NextArg() { + return d.ArgErr() + } + } + return nil +} + +// Interface guard +var _ caddy.StorageConverter = (*FileStorage)(nil) diff --git a/storage.go b/storage.go index f695a49b..b325b7bb 100644 --- a/storage.go +++ b/storage.go @@ -22,10 +22,6 @@ import ( "github.com/mholt/certmagic" ) -func init() { - RegisterModule(fileStorage{}) -} - // StorageConverter is a type that can convert itself // to a valid, usable certmagic.Storage value. (The // value might be short-lived.) This interface allows @@ -35,23 +31,6 @@ type StorageConverter interface { CertMagicStorage() (certmagic.Storage, error) } -// fileStorage is a certmagic.Storage wrapper for certmagic.FileStorage. -type fileStorage struct { - Root string `json:"root"` -} - -// CaddyModule returns the Caddy module information. -func (fileStorage) CaddyModule() ModuleInfo { - return ModuleInfo{ - Name: "caddy.storage.file_system", - New: func() Module { return new(fileStorage) }, - } -} - -func (s fileStorage) CertMagicStorage() (certmagic.Storage, error) { - return &certmagic.FileStorage{Path: s.Root}, nil -} - // homeDir returns the best guess of the current user's home // directory from environment variables. If unknown, "." (the // current directory) is returned instead. @@ -80,6 +59,3 @@ func dataDir() string { } return filepath.Join(baseDir, "caddy") } - -// Interface guard -var _ StorageConverter = fileStorage{}