diff --git a/caddy.go b/caddy.go index 1ae341b9..7a80d176 100644 --- a/caddy.go +++ b/caddy.go @@ -432,31 +432,7 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r cdyfile = CaddyfileInput{} } - stypeName := cdyfile.ServerType() - - stype, err := getServerType(stypeName) - if err != nil { - return err - } - - inst.caddyfileInput = cdyfile - - sblocks, err := loadServerBlocks(stypeName, cdyfile.Path(), bytes.NewReader(cdyfile.Body())) - if err != nil { - return err - } - - inst.context = stype.NewContext() - if inst.context == nil { - return fmt.Errorf("server type %s produced a nil Context", stypeName) - } - - sblocks, err = inst.context.InspectServerBlocks(cdyfile.Path(), sblocks) - if err != nil { - return err - } - - err = executeDirectives(inst, cdyfile.Path(), stype.Directives(), sblocks) + err := ValidateAndExecuteDirectives(cdyfile, inst, false) if err != nil { return err } @@ -516,9 +492,48 @@ func startWithListenerFds(cdyfile Input, inst *Instance, restartFds map[string]r return nil } -func executeDirectives(inst *Instance, filename string, - directives []string, sblocks []caddyfile.ServerBlock) error { +func ValidateAndExecuteDirectives(cdyfile Input, inst *Instance, justValidate bool) error { + // If parsing only inst will be nil, create an instance for this function call only. + if justValidate { + inst = &Instance{serverType: cdyfile.ServerType(), wg: new(sync.WaitGroup)} + } + + stypeName := cdyfile.ServerType() + + stype, err := getServerType(stypeName) + if err != nil { + return err + } + + inst.caddyfileInput = cdyfile + + sblocks, err := loadServerBlocks(stypeName, cdyfile.Path(), bytes.NewReader(cdyfile.Body())) + if err != nil { + return err + } + + inst.context = stype.NewContext() + if inst.context == nil { + return fmt.Errorf("server type %s produced a nil Context", stypeName) + } + + sblocks, err = inst.context.InspectServerBlocks(cdyfile.Path(), sblocks) + if err != nil { + return err + } + + err = executeDirectives(inst, cdyfile.Path(), stype.Directives(), sblocks, justValidate) + if err != nil { + return err + } + + return nil + +} + +func executeDirectives(inst *Instance, filename string, + directives []string, sblocks []caddyfile.ServerBlock, justValidate bool) error { // map of server block ID to map of directive name to whatever. storages := make(map[int]map[string]interface{}) @@ -568,12 +583,14 @@ func executeDirectives(inst *Instance, filename string, } } - // See if there are any callbacks to execute after this directive - if allCallbacks, ok := parsingCallbacks[inst.serverType]; ok { - callbacks := allCallbacks[dir] - for _, callback := range callbacks { - if err := callback(inst.context); err != nil { - return err + if !justValidate { + // See if there are any callbacks to execute after this directive + if allCallbacks, ok := parsingCallbacks[inst.serverType]; ok { + callbacks := allCallbacks[dir] + for _, callback := range callbacks { + if err := callback(inst.context); err != nil { + return err + } } } } diff --git a/caddy/caddymain/run.go b/caddy/caddymain/run.go index 71d05db7..0d8e4de1 100644 --- a/caddy/caddymain/run.go +++ b/caddy/caddymain/run.go @@ -40,6 +40,7 @@ func init() { flag.StringVar(&revoke, "revoke", "", "Hostname for which to revoke the certificate") flag.StringVar(&serverType, "type", "http", "Type of server to run") flag.BoolVar(&version, "version", false, "Show version") + flag.BoolVar(&validate, "validate", false, "Parse the Caddyfile but do not start the server") caddy.RegisterCaddyfileLoader("flag", caddy.LoaderFunc(confLoader)) caddy.SetDefaultCaddyfileLoader("default", caddy.LoaderFunc(defaultLoader)) @@ -74,7 +75,7 @@ func Run() { if revoke != "" { err := caddytls.Revoke(revoke) if err != nil { - mustLogFatalf(err.Error()) + mustLogFatalf("%v", err.Error()) } fmt.Printf("Revoked certificate for %s\n", revoke) os.Exit(0) @@ -94,19 +95,29 @@ func Run() { // Set CPU cap err := setCPU(cpu) if err != nil { - mustLogFatalf(err.Error()) + mustLogFatalf("%v", err.Error()) } // Get Caddyfile input - caddyfile, err := caddy.LoadCaddyfile(serverType) + caddyfileinput, err := caddy.LoadCaddyfile(serverType) if err != nil { - mustLogFatalf(err.Error()) + mustLogFatalf("%v", err.Error()) + } + + if validate { + justValidate := true + err := caddy.ValidateAndExecuteDirectives(caddyfileinput, nil, justValidate) + if err != nil { + mustLogFatalf("%v", err.Error()) + } + log.Println("[INFO] Caddyfile Valid") + os.Exit(0) } // Start your engines - instance, err := caddy.Start(caddyfile) + instance, err := caddy.Start(caddyfileinput) if err != nil { - mustLogFatalf(err.Error()) + mustLogFatalf("%v", err.Error()) } // Twiddle your thumbs @@ -226,6 +237,7 @@ var ( revoke string version bool plugins bool + validate bool ) // Build information obtained with the help of -ldflags