From a798e0c95191e07996c2a0d79087962d14e06464 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Mon, 20 Jun 2016 11:44:20 -0600 Subject: [PATCH] Refactor how caddy.Context is stored and used - Server types no longer need to store their own contexts; they are stored on the caddy.Instance, which means each context will be properly GC'ed when the instance is stopped. Server types should use type assertions to convert from caddy.Context to their concrete context type when they need to use it. - Pass the entire context into httpserver.GetConfig instead of only the Key field. - caddy.NewTestController now requires a server type string so it can create a controller with the proper concrete context associated with that server type. Tests still need more attention so that we can test the proper creation of startup functions, etc. --- caddy.go | 16 ++++--- caddyhttp/basicauth/setup.go | 4 +- caddyhttp/basicauth/setup_test.go | 7 +-- caddyhttp/bind/bind.go | 2 +- caddyhttp/bind/bind_test.go | 5 ++- caddyhttp/browse/setup.go | 4 +- caddyhttp/browse/setup_test.go | 5 ++- caddyhttp/errors/setup.go | 4 +- caddyhttp/errors/setup_test.go | 7 +-- caddyhttp/expvar/setup.go | 2 +- caddyhttp/expvar/setup_test.go | 12 +++--- caddyhttp/extensions/setup.go | 4 +- caddyhttp/extensions/setup_test.go | 7 +-- caddyhttp/fastcgi/setup.go | 2 +- caddyhttp/fastcgi/setup_test.go | 7 +-- caddyhttp/gzip/setup.go | 2 +- caddyhttp/gzip/setup_test.go | 7 +-- caddyhttp/header/setup.go | 2 +- caddyhttp/header/setup_test.go | 7 +-- caddyhttp/httpserver/https.go | 36 ++++++++-------- caddyhttp/httpserver/plugin.go | 57 ++++++++++++------------- caddyhttp/internalsrv/setup.go | 2 +- caddyhttp/internalsrv/setup_test.go | 7 +-- caddyhttp/log/setup.go | 2 +- caddyhttp/log/setup_test.go | 9 ++-- caddyhttp/markdown/setup.go | 4 +- caddyhttp/markdown/setup_test.go | 9 ++-- caddyhttp/mime/setup.go | 2 +- caddyhttp/mime/setup_test.go | 7 +-- caddyhttp/pprof/setup.go | 2 +- caddyhttp/pprof/setup_test.go | 3 +- caddyhttp/proxy/setup.go | 2 +- caddyhttp/proxy/setup_test.go | 5 ++- caddyhttp/redirect/setup.go | 4 +- caddyhttp/redirect/setup_test.go | 5 ++- caddyhttp/rewrite/setup.go | 2 +- caddyhttp/rewrite/setup_test.go | 9 ++-- caddyhttp/root/root.go | 2 +- caddyhttp/root/root_test.go | 5 +-- caddyhttp/templates/setup.go | 2 +- caddyhttp/templates/setup_test.go | 7 +-- caddyhttp/websocket/setup.go | 2 +- caddyhttp/websocket/setup_test.go | 7 +-- caddytls/config.go | 3 +- caddytls/setup.go | 2 +- caddytls/setup_test.go | 38 ++++++++--------- controller.go | 12 ++++-- plugins.go | 11 +++-- startupshutdown/startupshutdown_test.go | 2 +- 49 files changed, 199 insertions(+), 167 deletions(-) diff --git a/caddy.go b/caddy.go index 85913bb8b..e011be8eb 100644 --- a/caddy.go +++ b/caddy.go @@ -67,7 +67,10 @@ type Instance struct { // wg is used to wait for all servers to shut down wg *sync.WaitGroup - // servers is the list of servers with their listeners... + // context is the context created for this instance. + context Context + + // servers is the list of servers with their listeners. servers []serverListener // these are callbacks to execute when certain events happen @@ -386,9 +389,12 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r return err } - ctx := stype.NewContext() + inst.context = stype.NewContext() + if inst.context == nil { + return fmt.Errorf("server type %s produced a nil Context", stypeName) + } - sblocks, err = ctx.InspectServerBlocks(cdyfile.Path(), sblocks) + sblocks, err = inst.context.InspectServerBlocks(cdyfile.Path(), sblocks) if err != nil { return err } @@ -398,7 +404,7 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r return err } - slist, err := ctx.MakeServers() + slist, err := inst.context.MakeServers() if err != nil { return err } @@ -496,7 +502,7 @@ func executeDirectives(inst *Instance, filename string, if allCallbacks, ok := parsingCallbacks[inst.serverType]; ok { callbacks := allCallbacks[dir] for _, callback := range callbacks { - if err := callback(); err != nil { + if err := callback(inst.context); err != nil { return err } } diff --git a/caddyhttp/basicauth/setup.go b/caddyhttp/basicauth/setup.go index e9c691b38..7dc4e8f2c 100644 --- a/caddyhttp/basicauth/setup.go +++ b/caddyhttp/basicauth/setup.go @@ -16,7 +16,7 @@ func init() { // setup configures a new BasicAuth middleware instance. func setup(c *caddy.Controller) error { - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) root := cfg.Root rules, err := basicAuthParse(c) @@ -37,7 +37,7 @@ func setup(c *caddy.Controller) error { func basicAuthParse(c *caddy.Controller) ([]Rule, error) { var rules []Rule - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) var err error for c.Next() { diff --git a/caddyhttp/basicauth/setup_test.go b/caddyhttp/basicauth/setup_test.go index c1245a9e1..80b4db39b 100644 --- a/caddyhttp/basicauth/setup_test.go +++ b/caddyhttp/basicauth/setup_test.go @@ -12,11 +12,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`basicauth user pwd`)) + c := caddy.NewTestController("http", `basicauth user pwd`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, but got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -87,7 +88,7 @@ md5:$apr1$l42y8rex$pOA2VJ0x/0TwaFeAF9nX61` } for i, test := range tests { - actual, err := basicAuthParse(caddy.NewTestController(test.input)) + actual, err := basicAuthParse(caddy.NewTestController("http", test.input)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/bind/bind.go b/caddyhttp/bind/bind.go index 460bd5b0e..c69aa0b1d 100644 --- a/caddyhttp/bind/bind.go +++ b/caddyhttp/bind/bind.go @@ -13,7 +13,7 @@ func init() { } func setupBind(c *caddy.Controller) error { - config := httpserver.GetConfig(c.Key) + config := httpserver.GetConfig(c) for c.Next() { if !c.Args(&config.ListenHost) { return c.ArgErr() diff --git a/caddyhttp/bind/bind_test.go b/caddyhttp/bind/bind_test.go index 330d5427d..8d81f84af 100644 --- a/caddyhttp/bind/bind_test.go +++ b/caddyhttp/bind/bind_test.go @@ -8,12 +8,13 @@ import ( ) func TestSetupBind(t *testing.T) { - err := setupBind(caddy.NewTestController(`bind 1.2.3.4`)) + c := caddy.NewTestController("http", `bind 1.2.3.4`) + err := setupBind(c) if err != nil { t.Fatalf("Expected no errors, but got: %v", err) } - cfg := httpserver.GetConfig("") + cfg := httpserver.GetConfig(c) if got, want := cfg.ListenHost, "1.2.3.4"; got != want { t.Errorf("Expected the config's ListenHost to be %s, was %s", want, got) } diff --git a/caddyhttp/browse/setup.go b/caddyhttp/browse/setup.go index 690f97d24..d6ceddd22 100644 --- a/caddyhttp/browse/setup.go +++ b/caddyhttp/browse/setup.go @@ -29,7 +29,7 @@ func setup(c *caddy.Controller) error { IgnoreIndexes: false, } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { b.Next = next return b }) @@ -40,7 +40,7 @@ func setup(c *caddy.Controller) error { func browseParse(c *caddy.Controller) ([]Config, error) { var configs []Config - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) appendCfg := func(bc Config) error { for _, c := range configs { diff --git a/caddyhttp/browse/setup_test.go b/caddyhttp/browse/setup_test.go index fadb7fa1e..e6cb16515 100644 --- a/caddyhttp/browse/setup_test.go +++ b/caddyhttp/browse/setup_test.go @@ -49,14 +49,15 @@ func TestSetup(t *testing.T) { {"browse " + tempDirPath + "\n browse " + tempDirPath, nil, true}, } { - err := setup(caddy.NewTestController(test.input)) + c := caddy.NewTestController("http", test.input) + err := setup(c) if err != nil && !test.shouldErr { t.Errorf("Test case #%d recieved an error of %v", i, err) } if test.expectedPathScope == nil { continue } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() mid := mids[len(mids)-1] recievedConfigs := mid(nil).(Browse).Configs for j, config := range recievedConfigs { diff --git a/caddyhttp/errors/setup.go b/caddyhttp/errors/setup.go index f43c95e97..36ef74d55 100644 --- a/caddyhttp/errors/setup.go +++ b/caddyhttp/errors/setup.go @@ -62,7 +62,7 @@ func setup(c *caddy.Controller) error { return nil }) - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { handler.Next = next return handler }) @@ -76,7 +76,7 @@ func errorsParse(c *caddy.Controller) (*ErrorHandler, error) { // same instance of the handler, not a copy. handler := &ErrorHandler{ErrorPages: make(map[int]string)} - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) optionalBlock := func() (bool, error) { var hadBlock bool diff --git a/caddyhttp/errors/setup_test.go b/caddyhttp/errors/setup_test.go index aed907ee8..4244de17d 100644 --- a/caddyhttp/errors/setup_test.go +++ b/caddyhttp/errors/setup_test.go @@ -8,11 +8,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`errors`)) + c := caddy.NewTestController("http", `errors`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middlewares, was nil instead") } @@ -104,7 +105,7 @@ func TestErrorsParse(t *testing.T) { }}, } for i, test := range tests { - actualErrorsRule, err := errorsParse(caddy.NewTestController(test.inputErrorsRules)) + actualErrorsRule, err := errorsParse(caddy.NewTestController("http", test.inputErrorsRules)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/expvar/setup.go b/caddyhttp/expvar/setup.go index 4bbe69f08..e411844e9 100644 --- a/caddyhttp/expvar/setup.go +++ b/caddyhttp/expvar/setup.go @@ -28,7 +28,7 @@ func setup(c *caddy.Controller) error { ev := ExpVar{Resource: resource} - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { ev.Next = next return ev }) diff --git a/caddyhttp/expvar/setup_test.go b/caddyhttp/expvar/setup_test.go index 96dd4b038..b53719ebc 100644 --- a/caddyhttp/expvar/setup_test.go +++ b/caddyhttp/expvar/setup_test.go @@ -8,25 +8,27 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`expvar`)) + c := caddy.NewTestController("http", `expvar`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } - err = setup(caddy.NewTestController(`expvar /d/v`)) + c = caddy.NewTestController("http", `expvar /d/v`) + err = setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids = httpserver.GetConfig("").Middleware() + mids = httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } - handler := mids[1](httpserver.EmptyNext) + handler := mids[0](httpserver.EmptyNext) myHandler, ok := handler.(ExpVar) if !ok { t.Fatalf("Expected handler to be type ExpVar, got: %#v", handler) diff --git a/caddyhttp/extensions/setup.go b/caddyhttp/extensions/setup.go index 4a1917a14..5cec873a0 100644 --- a/caddyhttp/extensions/setup.go +++ b/caddyhttp/extensions/setup.go @@ -14,7 +14,7 @@ func init() { // setup configures a new instance of 'extensions' middleware for clean URLs. func setup(c *caddy.Controller) error { - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) root := cfg.Root exts, err := extParse(c) @@ -22,7 +22,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Ext{ Next: next, Extensions: exts, diff --git a/caddyhttp/extensions/setup_test.go b/caddyhttp/extensions/setup_test.go index f6248beb5..26c50e3c4 100644 --- a/caddyhttp/extensions/setup_test.go +++ b/caddyhttp/extensions/setup_test.go @@ -8,12 +8,13 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`ext .html .htm .php`)) + c := caddy.NewTestController("http", `ext .html .htm .php`) + err := setup(c) if err != nil { t.Fatalf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, had 0 instead") } @@ -51,7 +52,7 @@ func TestExtParse(t *testing.T) { {`ext .txt .php .xml`, false, []string{".txt", ".php", ".xml"}}, } for i, test := range tests { - actualExts, err := extParse(caddy.NewTestController(test.inputExts)) + actualExts, err := extParse(caddy.NewTestController("http", test.inputExts)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/fastcgi/setup.go b/caddyhttp/fastcgi/setup.go index dd32c593f..c7650faa0 100644 --- a/caddyhttp/fastcgi/setup.go +++ b/caddyhttp/fastcgi/setup.go @@ -18,7 +18,7 @@ func init() { // setup configures a new FastCGI middleware instance. func setup(c *caddy.Controller) error { - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) absRoot, err := filepath.Abs(cfg.Root) if err != nil { return err diff --git a/caddyhttp/fastcgi/setup_test.go b/caddyhttp/fastcgi/setup_test.go index b28b147b8..123b4b9e8 100644 --- a/caddyhttp/fastcgi/setup_test.go +++ b/caddyhttp/fastcgi/setup_test.go @@ -9,11 +9,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`fastcgi / 127.0.0.1:9000`)) + c := caddy.NewTestController("http", `fastcgi / 127.0.0.1:9000`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -73,7 +74,7 @@ func TestFastcgiParse(t *testing.T) { }}}, } for i, test := range tests { - actualFastcgiConfigs, err := fastcgiParse(caddy.NewTestController(test.inputFastcgiConfig)) + actualFastcgiConfigs, err := fastcgiParse(caddy.NewTestController("http", test.inputFastcgiConfig)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/gzip/setup.go b/caddyhttp/gzip/setup.go index 824ac2141..0a22e23c6 100644 --- a/caddyhttp/gzip/setup.go +++ b/caddyhttp/gzip/setup.go @@ -16,7 +16,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Gzip{Next: next, Configs: configs} }) diff --git a/caddyhttp/gzip/setup_test.go b/caddyhttp/gzip/setup_test.go index a71c9b19f..f57da0220 100644 --- a/caddyhttp/gzip/setup_test.go +++ b/caddyhttp/gzip/setup_test.go @@ -8,11 +8,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`gzip`)) + c := caddy.NewTestController("http", `gzip`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, but got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if mids == nil { t.Fatal("Expected middleware, was nil instead") } @@ -90,7 +91,7 @@ func TestSetup(t *testing.T) { `, false}, } for i, test := range tests { - _, err := gzipParse(caddy.NewTestController(test.input)) + _, err := gzipParse(caddy.NewTestController("http", test.input)) if test.shouldErr && err == nil { t.Errorf("Test %v: Expected error but found nil", i) } else if !test.shouldErr && err != nil { diff --git a/caddyhttp/header/setup.go b/caddyhttp/header/setup.go index be0320045..17dc8b403 100644 --- a/caddyhttp/header/setup.go +++ b/caddyhttp/header/setup.go @@ -19,7 +19,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Headers{Next: next, Rules: rules} }) diff --git a/caddyhttp/header/setup_test.go b/caddyhttp/header/setup_test.go index e3b6cbf19..3c544d1c3 100644 --- a/caddyhttp/header/setup_test.go +++ b/caddyhttp/header/setup_test.go @@ -9,12 +9,13 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`header / Foo Bar`)) + c := caddy.NewTestController("http", `header / Foo Bar`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, but got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, had 0 instead") } @@ -52,7 +53,7 @@ func TestHeadersParse(t *testing.T) { } for i, test := range tests { - actual, err := headersParse(caddy.NewTestController(test.input)) + actual, err := headersParse(caddy.NewTestController("http", test.input)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/httpserver/https.go b/caddyhttp/httpserver/https.go index b93a85439..b1ae5369e 100644 --- a/caddyhttp/httpserver/https.go +++ b/caddyhttp/httpserver/https.go @@ -4,37 +4,37 @@ import ( "net" "net/http" + "github.com/mholt/caddy" "github.com/mholt/caddy/caddytls" ) -func activateHTTPS() error { - // TODO: Is this loop a bug? Should we scope this method to just a single context? (restarts...?) - for _, ctx := range contexts { - // pre-screen each config and earmark the ones that qualify for managed TLS - markQualifiedForAutoHTTPS(ctx.siteConfigs) +func activateHTTPS(cctx caddy.Context) error { + ctx := cctx.(*httpContext) - // place certificates and keys on disk - for _, c := range ctx.siteConfigs { - err := c.TLS.ObtainCert(true) - if err != nil { - return err - } - } + // pre-screen each config and earmark the ones that qualify for managed TLS + markQualifiedForAutoHTTPS(ctx.siteConfigs) - // update TLS configurations - err := enableAutoHTTPS(ctx.siteConfigs, true) + // place certificates and keys on disk + for _, c := range ctx.siteConfigs { + err := c.TLS.ObtainCert(true) if err != nil { return err } - - // set up redirects - ctx.siteConfigs = makePlaintextRedirects(ctx.siteConfigs) } + // update TLS configurations + err := enableAutoHTTPS(ctx.siteConfigs, true) + if err != nil { + return err + } + + // set up redirects + ctx.siteConfigs = makePlaintextRedirects(ctx.siteConfigs) + // renew all relevant certificates that need renewal. this is important // to do right away so we guarantee that renewals aren't missed, and // also the user can respond to any potential errors that occur. - err := caddytls.RenewManagedCertificates(true) + err = caddytls.RenewManagedCertificates(true) if err != nil { return err } diff --git a/caddyhttp/httpserver/plugin.go b/caddyhttp/httpserver/plugin.go index bfbcb0097..5965930a0 100644 --- a/caddyhttp/httpserver/plugin.go +++ b/caddyhttp/httpserver/plugin.go @@ -44,16 +44,11 @@ func init() { }) caddy.RegisterCaddyfileLoader("short", caddy.LoaderFunc(shortCaddyfileLoader)) caddy.RegisterParsingCallback(serverType, "tls", activateHTTPS) - caddytls.RegisterConfigGetter(serverType, func(key string) *caddytls.Config { return GetConfig(key).TLS }) + caddytls.RegisterConfigGetter(serverType, func(c *caddy.Controller) *caddytls.Config { return GetConfig(c).TLS }) } -var contexts []*httpContext - func newContext() caddy.Context { - context := &httpContext{keysToSiteConfigs: make(map[string]*SiteConfig)} - // put the new context at start to allow setup of directives on new instance - contexts = append([]*httpContext{context}, contexts...) - return context + return &httpContext{keysToSiteConfigs: make(map[string]*SiteConfig)} } type httpContext struct { @@ -67,6 +62,11 @@ type httpContext struct { siteConfigs []*SiteConfig } +func (h *httpContext) saveConfig(key string, cfg *SiteConfig) { + h.siteConfigs = append(h.siteConfigs, cfg) + h.keysToSiteConfigs[key] = cfg +} + // InspectServerBlocks make sure that everything checks out before // executing directives and otherwise prepares the directives to // be parsed and executed. @@ -89,15 +89,14 @@ func (h *httpContext) InspectServerBlocks(sourceFile string, serverBlocks []cadd TLS: &caddytls.Config{Hostname: addr.Host}, HiddenFiles: []string{sourceFile}, } - h.siteConfigs = append(h.siteConfigs, cfg) - h.keysToSiteConfigs[key] = cfg + h.saveConfig(key, cfg) } } // For sites that have gzip (which gets chained in // before the error handler) we should ensure that the // errors directive also appears so error pages aren't - // written after the gzip writer is closed. + // written after the gzip writer is closed. See #616. for _, sb := range serverBlocks { _, hasGzip := sb.Tokens["gzip"] _, hasErrors := sb.Tokens["errors"] @@ -129,6 +128,12 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) { // is incorrect for this site. cfg.Addr.Scheme = "https" } + if cfg.Addr.Port == "" { + // this is vital, otherwise the function call below that + // sets the listener address will use the default port + // instead of 443 because it doesn't know about TLS. + cfg.Addr.Port = "443" + } } // we must map (group) each config to a bind address @@ -150,27 +155,19 @@ func (h *httpContext) MakeServers() ([]caddy.Server, error) { return servers, nil } -// GetConfig gets a SiteConfig that is keyed by addrKey. -// It creates an empty one in the latest context if -// the key does not exist in any context, so it -// will never return nil. If no contexts exist (which -// should never happen except in tests), it creates a -// new context in which to put it. -func GetConfig(addrKey string) *SiteConfig { - for _, context := range contexts { - if cfg, ok := context.keysToSiteConfigs[addrKey]; ok { - return cfg - } +// GetConfig gets the SiteConfig that corresponds to c. +// If none exist (should only happen in tests), then a +// new, empty one will be created. +func GetConfig(c *caddy.Controller) *SiteConfig { + ctx := c.Context().(*httpContext) + if cfg, ok := ctx.keysToSiteConfigs[c.Key]; ok { + return cfg } - if len(contexts) == 0 { - // this shouldn't happen except in tests - newContext() - } - cfg := &SiteConfig{Root: Root, TLS: new(caddytls.Config)} - defaultCtx := contexts[len(contexts)-1] - defaultCtx.siteConfigs = append(defaultCtx.siteConfigs, cfg) - defaultCtx.keysToSiteConfigs[addrKey] = cfg - return cfg + // we should only get here during tests because directive + // actions typically skip the server blocks where we make + // the configs + ctx.saveConfig(c.Key, &SiteConfig{Root: Root, TLS: new(caddytls.Config)}) + return GetConfig(c) } // shortCaddyfileLoader loads a Caddyfile if positional arguments are diff --git a/caddyhttp/internalsrv/setup.go b/caddyhttp/internalsrv/setup.go index ed69c22b8..f2f4a68c6 100644 --- a/caddyhttp/internalsrv/setup.go +++ b/caddyhttp/internalsrv/setup.go @@ -19,7 +19,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Internal{Next: next, Paths: paths} }) diff --git a/caddyhttp/internalsrv/setup_test.go b/caddyhttp/internalsrv/setup_test.go index e67982ce0..b7758772f 100644 --- a/caddyhttp/internalsrv/setup_test.go +++ b/caddyhttp/internalsrv/setup_test.go @@ -8,11 +8,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`internal /internal`)) + c := caddy.NewTestController("http", `internal /internal`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -46,7 +47,7 @@ func TestInternalParse(t *testing.T) { internal /internal2`, false, []string{"/internal1", "/internal2"}}, } for i, test := range tests { - actualInternalPaths, err := internalParse(caddy.NewTestController(test.inputInternalPaths)) + actualInternalPaths, err := internalParse(caddy.NewTestController("http", test.inputInternalPaths)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/log/setup.go b/caddyhttp/log/setup.go index 9aa3d9a49..ddb39da6d 100644 --- a/caddyhttp/log/setup.go +++ b/caddyhttp/log/setup.go @@ -53,7 +53,7 @@ func setup(c *caddy.Controller) error { return nil }) - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Logger{Next: next, Rules: rules, ErrorFunc: httpserver.DefaultErrorFunc} }) diff --git a/caddyhttp/log/setup_test.go b/caddyhttp/log/setup_test.go index 436002ac3..58191804e 100644 --- a/caddyhttp/log/setup_test.go +++ b/caddyhttp/log/setup_test.go @@ -8,13 +8,12 @@ import ( ) func TestSetup(t *testing.T) { - cfg := httpserver.GetConfig("") - - err := setup(caddy.NewTestController(`log`)) + c := caddy.NewTestController("http", `log`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - + cfg := httpserver.GetConfig(c) mids := cfg.Middleware() if mids == nil { t.Fatal("Expected middleware, was nil instead") @@ -114,7 +113,7 @@ func TestLogParse(t *testing.T) { }}}, } for i, test := range tests { - c := caddy.NewTestController(test.inputLogRules) + c := caddy.NewTestController("http", test.inputLogRules) actualLogRules, err := logParse(c) if err == nil && test.shouldErr { diff --git a/caddyhttp/markdown/setup.go b/caddyhttp/markdown/setup.go index 5c15417f0..24dc6fcf6 100644 --- a/caddyhttp/markdown/setup.go +++ b/caddyhttp/markdown/setup.go @@ -23,7 +23,7 @@ func setup(c *caddy.Controller) error { return err } - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) md := Markdown{ Root: cfg.Root, @@ -82,7 +82,7 @@ func markdownParse(c *caddy.Controller) ([]*Config, error) { } func loadParams(c *caddy.Controller, mdc *Config) error { - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) switch c.Val() { case "ext": diff --git a/caddyhttp/markdown/setup_test.go b/caddyhttp/markdown/setup_test.go index 2880a230f..427e242cd 100644 --- a/caddyhttp/markdown/setup_test.go +++ b/caddyhttp/markdown/setup_test.go @@ -12,11 +12,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`markdown /blog`)) + c := caddy.NewTestController("http", `markdown /blog`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -78,8 +79,8 @@ func TestMarkdownParse(t *testing.T) { SetTemplate(tmpl, "", "./testdata/tpl_with_include.html") for i, test := range tests { - c := caddy.NewTestController(test.inputMarkdownConfig) - httpserver.GetConfig("").Root = "./testdata" + c := caddy.NewTestController("http", test.inputMarkdownConfig) + httpserver.GetConfig(c).Root = "./testdata" actualMarkdownConfigs, err := markdownParse(c) if err == nil && test.shouldErr { diff --git a/caddyhttp/mime/setup.go b/caddyhttp/mime/setup.go index 28e31a7ce..bca622436 100644 --- a/caddyhttp/mime/setup.go +++ b/caddyhttp/mime/setup.go @@ -22,7 +22,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Mime{Next: next, Configs: configs} }) diff --git a/caddyhttp/mime/setup_test.go b/caddyhttp/mime/setup_test.go index 3d1fce605..571acf17e 100644 --- a/caddyhttp/mime/setup_test.go +++ b/caddyhttp/mime/setup_test.go @@ -8,11 +8,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`mime .txt text/plain`)) + c := caddy.NewTestController("http", `mime .txt text/plain`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, but got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, but had 0 instead") } @@ -52,7 +53,7 @@ func TestSetup(t *testing.T) { {`mime .txt text/plain`, false}, } for i, test := range tests { - m, err := mimeParse(caddy.NewTestController(test.input)) + m, err := mimeParse(caddy.NewTestController("http", test.input)) if test.shouldErr && err == nil { t.Errorf("Test %v: Expected error but found nil %v", i, m) } else if !test.shouldErr && err != nil { diff --git a/caddyhttp/pprof/setup.go b/caddyhttp/pprof/setup.go index 7a66cf001..638d5e126 100644 --- a/caddyhttp/pprof/setup.go +++ b/caddyhttp/pprof/setup.go @@ -29,7 +29,7 @@ func setup(c *caddy.Controller) error { found = true } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return &Handler{Next: next, Mux: NewMux()} }) diff --git a/caddyhttp/pprof/setup_test.go b/caddyhttp/pprof/setup_test.go index d53257d2b..f51303ec8 100644 --- a/caddyhttp/pprof/setup_test.go +++ b/caddyhttp/pprof/setup_test.go @@ -21,7 +21,8 @@ func TestSetup(t *testing.T) { pprof`, true}, } for i, test := range tests { - err := setup(caddy.NewTestController(test.input)) + c := caddy.NewTestController("http", test.input) + err := setup(c) if test.shouldErr && err == nil { t.Errorf("Test %v: Expected error but found nil", i) } else if !test.shouldErr && err != nil { diff --git a/caddyhttp/proxy/setup.go b/caddyhttp/proxy/setup.go index 600589020..c25b041a8 100644 --- a/caddyhttp/proxy/setup.go +++ b/caddyhttp/proxy/setup.go @@ -18,7 +18,7 @@ func setup(c *caddy.Controller) error { if err != nil { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Proxy{Next: next, Upstreams: upstreams} }) return nil diff --git a/caddyhttp/proxy/setup_test.go b/caddyhttp/proxy/setup_test.go index c48d3479a..949104dab 100644 --- a/caddyhttp/proxy/setup_test.go +++ b/caddyhttp/proxy/setup_test.go @@ -112,14 +112,15 @@ func TestSetup(t *testing.T) { }, }, } { - err := setup(caddy.NewTestController(test.input)) + c := caddy.NewTestController("http", test.input) + err := setup(c) if err != nil && !test.shouldErr { t.Errorf("Test case #%d received an error of %v", i, err) } else if test.shouldErr { continue } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() mid := mids[len(mids)-1] upstreams := mid(nil).(Proxy).Upstreams diff --git a/caddyhttp/redirect/setup.go b/caddyhttp/redirect/setup.go index bc838115a..d45d2b609 100644 --- a/caddyhttp/redirect/setup.go +++ b/caddyhttp/redirect/setup.go @@ -21,7 +21,7 @@ func setup(c *caddy.Controller) error { return err } - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Redirect{Next: next, Rules: rules} }) @@ -31,7 +31,7 @@ func setup(c *caddy.Controller) error { func redirParse(c *caddy.Controller) ([]Rule, error) { var redirects []Rule - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) // setRedirCode sets the redirect code for rule if it can, or returns an error setRedirCode := func(code string, rule *Rule) error { diff --git a/caddyhttp/redirect/setup_test.go b/caddyhttp/redirect/setup_test.go index c4774cfaf..e0c5fde92 100644 --- a/caddyhttp/redirect/setup_test.go +++ b/caddyhttp/redirect/setup_test.go @@ -44,13 +44,14 @@ func TestSetup(t *testing.T) { // test case #9 tests the detection of duplicate redirections {"redir {\n /bar /foo 304 \n} redir {\n /bar /foo 304 \n}", true, []Rule{{}}}, } { - err := setup(caddy.NewTestController(test.input)) + c := caddy.NewTestController("http", test.input) + err := setup(c) if err != nil && !test.shouldErr { t.Errorf("Test case #%d recieved an error of %v", j, err) } else if test.shouldErr { continue } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() recievedRules := mids[len(mids)-1](nil).(Redirect).Rules for i, recievedRule := range recievedRules { diff --git a/caddyhttp/rewrite/setup.go b/caddyhttp/rewrite/setup.go index 9cf3b33b0..b81be34f4 100644 --- a/caddyhttp/rewrite/setup.go +++ b/caddyhttp/rewrite/setup.go @@ -23,7 +23,7 @@ func setup(c *caddy.Controller) error { return err } - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) cfg.AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return Rewrite{ diff --git a/caddyhttp/rewrite/setup_test.go b/caddyhttp/rewrite/setup_test.go index ec22aa3c3..3f32a15e9 100644 --- a/caddyhttp/rewrite/setup_test.go +++ b/caddyhttp/rewrite/setup_test.go @@ -10,11 +10,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`rewrite /from /to`)) + c := caddy.NewTestController("http", `rewrite /from /to`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, but got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, had 0 instead") } @@ -56,7 +57,7 @@ func TestRewriteParse(t *testing.T) { } for i, test := range simpleTests { - actual, err := rewriteParse(caddy.NewTestController(test.input)) + actual, err := rewriteParse(caddy.NewTestController("http", test.input)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) @@ -187,7 +188,7 @@ func TestRewriteParse(t *testing.T) { } for i, test := range regexpTests { - actual, err := rewriteParse(caddy.NewTestController(test.input)) + actual, err := rewriteParse(caddy.NewTestController("http", test.input)) if err == nil && test.shouldErr { t.Errorf("Test %d didn't error, but it should have", i) diff --git a/caddyhttp/root/root.go b/caddyhttp/root/root.go index d96309f9c..50ada1103 100644 --- a/caddyhttp/root/root.go +++ b/caddyhttp/root/root.go @@ -16,7 +16,7 @@ func init() { } func setupRoot(c *caddy.Controller) error { - config := httpserver.GetConfig(c.Key) + config := httpserver.GetConfig(c) for c.Next() { if !c.NextArg() { diff --git a/caddyhttp/root/root_test.go b/caddyhttp/root/root_test.go index 20b2c7a9b..471d9a24a 100644 --- a/caddyhttp/root/root_test.go +++ b/caddyhttp/root/root_test.go @@ -13,8 +13,6 @@ import ( ) func TestRoot(t *testing.T) { - cfg := httpserver.GetConfig("") - // Predefined error substrings parseErrContent := "Parse error:" unableToAccessErrContent := "Unable to access root path" @@ -65,8 +63,9 @@ func TestRoot(t *testing.T) { } for i, test := range tests { - c := caddy.NewTestController(test.input) + c := caddy.NewTestController("http", test.input) err := setupRoot(c) + cfg := httpserver.GetConfig(c) if test.shouldErr && err == nil { t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input) diff --git a/caddyhttp/templates/setup.go b/caddyhttp/templates/setup.go index 70363f91f..b8d1ca748 100644 --- a/caddyhttp/templates/setup.go +++ b/caddyhttp/templates/setup.go @@ -21,7 +21,7 @@ func setup(c *caddy.Controller) error { return err } - cfg := httpserver.GetConfig(c.Key) + cfg := httpserver.GetConfig(c) tmpls := Templates{ Rules: rules, diff --git a/caddyhttp/templates/setup_test.go b/caddyhttp/templates/setup_test.go index 2427afd45..c3287dffd 100644 --- a/caddyhttp/templates/setup_test.go +++ b/caddyhttp/templates/setup_test.go @@ -9,11 +9,12 @@ import ( ) func TestSetup(t *testing.T) { - err := setup(caddy.NewTestController(`templates`)) + c := caddy.NewTestController("http", `templates`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -81,7 +82,7 @@ func TestTemplatesParse(t *testing.T) { }}}, } for i, test := range tests { - c := caddy.NewTestController(test.inputTemplateConfig) + c := caddy.NewTestController("http", test.inputTemplateConfig) actualTemplateConfigs, err := templatesParse(c) if err == nil && test.shouldErr { diff --git a/caddyhttp/websocket/setup.go b/caddyhttp/websocket/setup.go index 5939aafb5..12a0e541a 100644 --- a/caddyhttp/websocket/setup.go +++ b/caddyhttp/websocket/setup.go @@ -22,7 +22,7 @@ func setup(c *caddy.Controller) error { GatewayInterface = caddy.AppName + "-CGI/1.1" ServerSoftware = caddy.AppName + "/" + caddy.AppVersion - httpserver.GetConfig(c.Key).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { + httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { return WebSocket{Next: next, Sockets: websocks} }) diff --git a/caddyhttp/websocket/setup_test.go b/caddyhttp/websocket/setup_test.go index f8b283304..e81f67d99 100644 --- a/caddyhttp/websocket/setup_test.go +++ b/caddyhttp/websocket/setup_test.go @@ -8,11 +8,12 @@ import ( ) func TestWebSocket(t *testing.T) { - err := setup(caddy.NewTestController(`websocket cat`)) + c := caddy.NewTestController("http", `websocket cat`) + err := setup(c) if err != nil { t.Errorf("Expected no errors, got: %v", err) } - mids := httpserver.GetConfig("").Middleware() + mids := httpserver.GetConfig(c).Middleware() if len(mids) == 0 { t.Fatal("Expected middleware, got 0 instead") } @@ -72,7 +73,7 @@ func TestWebSocketParse(t *testing.T) { }`, true, []Config{}}, } for i, test := range tests { - c := caddy.NewTestController(test.inputWebSocketConfig) + c := caddy.NewTestController("http", test.inputWebSocketConfig) actualWebSocketConfigs, err := webSocketParse(c) if err == nil && test.shouldErr { diff --git a/caddytls/config.go b/caddytls/config.go index 5250ecc32..91c745160 100644 --- a/caddytls/config.go +++ b/caddytls/config.go @@ -9,6 +9,7 @@ import ( "io/ioutil" "time" + "github.com/mholt/caddy" "github.com/xenolf/lego/acme" ) @@ -306,7 +307,7 @@ func MakeTLSConfig(configs []*Config) (*tls.Config, error) { } // ConfigGetter gets a Config keyed by key. -type ConfigGetter func(key string) *Config +type ConfigGetter func(c *caddy.Controller) *Config var configGetters = make(map[string]ConfigGetter) diff --git a/caddytls/setup.go b/caddytls/setup.go index 9db647e84..b0635e6fc 100644 --- a/caddytls/setup.go +++ b/caddytls/setup.go @@ -27,7 +27,7 @@ func setupTLS(c *caddy.Controller) error { if !ok { return fmt.Errorf("no caddytls.ConfigGetter for %s server type; must call RegisterConfigGetter", c.ServerType()) } - config := configGetter(c.Key) + config := configGetter(c) if config == nil { return fmt.Errorf("no caddytls.Config to set up for %s", c.Key) } diff --git a/caddytls/setup_test.go b/caddytls/setup_test.go index ceb1c2a4a..c86af78bf 100644 --- a/caddytls/setup_test.go +++ b/caddytls/setup_test.go @@ -33,8 +33,8 @@ func TestMain(m *testing.M) { func TestSetupParseBasic(t *testing.T) { cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(`tls ` + certFile + ` ` + keyFile + ``) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", `tls `+certFile+` `+keyFile+``) err := setupTLS(c) if err != nil { @@ -92,7 +92,7 @@ func TestSetupParseBasic(t *testing.T) { func TestSetupParseIncompleteParams(t *testing.T) { // Using tls without args is an error because it's unnecessary. - c := caddy.NewTestController(`tls`) + c := caddy.NewTestController("http", `tls`) err := setupTLS(c) if err == nil { t.Error("Expected an error, but didn't get one") @@ -105,8 +105,8 @@ func TestSetupParseWithOptionalParams(t *testing.T) { ciphers RSA-AES256-CBC-SHA ECDHE-RSA-AES128-GCM-SHA256 ECDHE-ECDSA-AES256-GCM-SHA384 }` cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", params) err := setupTLS(c) if err != nil { @@ -131,8 +131,8 @@ func TestSetupDefaultWithOptionalParams(t *testing.T) { ciphers RSA-3DES-EDE-CBC-SHA }` cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", params) err := setupTLS(c) if err != nil { @@ -149,8 +149,8 @@ func TestSetupParseWithWrongOptionalParams(t *testing.T) { protocols ssl tls }` cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", params) err := setupTLS(c) if err == nil { t.Errorf("Expected errors, but no error returned") @@ -161,8 +161,8 @@ func TestSetupParseWithWrongOptionalParams(t *testing.T) { ciphers not-valid-cipher }` cfg = new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c = caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c = caddy.NewTestController("http", params) err = setupTLS(c) if err == nil { t.Errorf("Expected errors, but no error returned") @@ -173,8 +173,8 @@ func TestSetupParseWithWrongOptionalParams(t *testing.T) { key_type ab123 }` cfg = new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c = caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c = caddy.NewTestController("http", params) err = setupTLS(c) if err == nil { t.Errorf("Expected errors, but no error returned") @@ -187,8 +187,8 @@ func TestSetupParseWithClientAuth(t *testing.T) { clients }` cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", params) err := setupTLS(c) if err == nil { t.Errorf("Expected an error, but no error returned") @@ -220,8 +220,8 @@ func TestSetupParseWithClientAuth(t *testing.T) { }`, tls.VerifyClientCertIfGiven, true, noCAs}, } { cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(caseData.params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", caseData.params) err := setupTLS(c) if caseData.expectedErr { if err == nil { @@ -256,8 +256,8 @@ func TestSetupParseWithKeyType(t *testing.T) { key_type p384 }` cfg := new(Config) - RegisterConfigGetter("", func(key string) *Config { return cfg }) - c := caddy.NewTestController(params) + RegisterConfigGetter("", func(c *caddy.Controller) *Config { return cfg }) + c := caddy.NewTestController("http", params) err := setupTLS(c) if err != nil { diff --git a/controller.go b/controller.go index 4be794821..c1fa627ae 100644 --- a/controller.go +++ b/controller.go @@ -70,16 +70,22 @@ func (c *Controller) OnShutdown(fn func() error) { c.instance.onShutdown = append(c.instance.onShutdown, fn) } -// NewTestController creates a new *Controller for +// Context gets the context associated with the instance associated with c. +func (c *Controller) Context() Context { + return c.instance.context +} + +// NewTestController creates a new Controller for // the input specified, with a filename of "Testfile". // The Config is bare, consisting only of a Root of cwd. // // Used primarily for testing but needs to be exported so // add-ons can use this as a convenience. Does not initialize // the server-block-related fields. -func NewTestController(input string) *Controller { +func NewTestController(serverType, input string) *Controller { + stype, _ := getServerType(serverType) return &Controller{ - instance: &Instance{serverType: ""}, + instance: &Instance{serverType: serverType, context: stype.NewContext()}, Dispenser: caddyfile.NewDispenser("Testfile", strings.NewReader(input)), OncePerServerBlock: func(f func() error) error { return f() }, } diff --git a/plugins.go b/plugins.go index 22e5e6f6c..895ed01ed 100644 --- a/plugins.go +++ b/plugins.go @@ -25,7 +25,7 @@ var ( // to list of callback functions. These aren't really // plugins on their own, but are often registered from // plugins. - parsingCallbacks = make(map[string]map[string][]func() error) + parsingCallbacks = make(map[string]map[string][]ParsingCallback) // caddyfileLoaders is the list of all Caddyfile loaders // in registration order. @@ -180,11 +180,16 @@ func RegisterPlugin(name string, plugin Plugin) { plugins[plugin.ServerType][name] = plugin } +// ParsingCallback is a function that is called after +// a directive's setup functions have been executed +// for all the server blocks. +type ParsingCallback func(Context) error + // RegisterParsingCallback registers callback to be called after // executing the directive afterDir for server type serverType. -func RegisterParsingCallback(serverType, afterDir string, callback func() error) { +func RegisterParsingCallback(serverType, afterDir string, callback ParsingCallback) { if _, ok := parsingCallbacks[serverType]; !ok { - parsingCallbacks[serverType] = make(map[string][]func() error) + parsingCallbacks[serverType] = make(map[string][]ParsingCallback) } parsingCallbacks[serverType][afterDir] = append(parsingCallbacks[serverType][afterDir], callback) } diff --git a/startupshutdown/startupshutdown_test.go b/startupshutdown/startupshutdown_test.go index 8bc98f9ab..edbad3a53 100644 --- a/startupshutdown/startupshutdown_test.go +++ b/startupshutdown/startupshutdown_test.go @@ -46,7 +46,7 @@ func TestStartup(t *testing.T) { } for i, test := range tests { - c := caddy.NewTestController(test.input) + c := caddy.NewTestController("http", test.input) err := registerCallback(c, fakeRegister) if err != nil { t.Errorf("Expected no errors, got: %v", err)