Commit a798e0c9 authored by Matthew Holt's avatar Matthew Holt

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.
parent 07b7c999
......@@ -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
}
}
......
......@@ -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() {
......
......@@ -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)
......
......@@ -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()
......
......@@ -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)
}
......
......@@ -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 {
......
......@@ -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 {
......
......@@ -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
......
......@@ -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)
......
......@@ -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
})
......
......@@ -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)
......
......@@ -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,
......
......@@ -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)
......
......@@ -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
......
......@@ -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)
......
......@@ -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}
})
......
......@@ -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 {
......
......@@ -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}
})
......
......@@ -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)
......
......@@ -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
}
......
......@@ -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
}
}
if len(contexts) == 0 {
// this shouldn't happen except in tests
newContext()
// 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
}
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
......
......@@ -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}
})
......
......@@ -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)
......
......@@ -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}
})
......
......@@ -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 {
......
......@@ -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":
......
......@@ -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 {
......
......@@ -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}
})
......
......@@ -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 {
......
......@@ -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()}
})
......
......@@ -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 {
......
......@@ -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
......
......@@ -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
......
......@@ -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 {
......
......@@ -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 {
......
......@@ -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{
......
......@@ -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)
......
......@@ -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() {
......
......@@ -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)
......
......@@ -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,
......
......@@ -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 {
......
......@@ -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}
})
......
......@@ -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 {
......
......@@ -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)
......
......@@ -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)
}
......
......@@ -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 {
......
......@@ -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() },
}
......
......@@ -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)
}
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment