diff --git a/caddy.go b/caddy.go index 62b12b63..2aa0c6a2 100644 --- a/caddy.go +++ b/caddy.go @@ -238,11 +238,19 @@ type Handle struct { current *Config } -// App returns the configured app named name. -// A nil value is returned if no app with that -// name is currently configured. -func (h Handle) App(name string) interface{} { - return h.current.apps[name] +// App returns the configured app named name. If no app with +// that name is currently configured, a new empty one will be +// instantiated. (The app module must still be plugged in.) +func (h Handle) App(name string) (interface{}, error) { + if app, ok := h.current.apps[name]; ok { + return app, nil + } + modVal, err := LoadModule(name, nil) + if err != nil { + return nil, fmt.Errorf("instantiating new module %s: %v", name, err) + } + h.current.apps[name] = modVal.(App) + return modVal, nil } // GetStorage returns the configured Caddy storage implementation. diff --git a/modules.go b/modules.go index 5a4e69fc..6afa6fb9 100644 --- a/modules.go +++ b/modules.go @@ -171,9 +171,12 @@ func LoadModule(name string, rawMsg json.RawMessage) (interface{}, error) { val = reflect.New(rv.Type()).Elem().Addr().Interface() } - err = json.Unmarshal(rawMsg, &val) - if err != nil { - return nil, fmt.Errorf("decoding module config: %s: %v", mod.Name, err) + // fill in its config only if there is a config to fill in + if len(rawMsg) > 0 { + err = json.Unmarshal(rawMsg, &val) + if err != nil { + return nil, fmt.Errorf("decoding module config: %s: %v", mod.Name, err) + } } if prov, ok := val.(Provisioner); ok { diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 437e48f7..de62b797 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -111,7 +111,11 @@ func (hc *httpModuleConfig) Stop() error { } func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error { - tlsApp := handle.App("tls").(*caddytls.TLS) + tlsAppIface, err := handle.App("tls") + if err != nil { + return fmt.Errorf("getting tls app: %v", err) + } + tlsApp := tlsAppIface.(*caddytls.TLS) for srvName, srv := range hc.Servers { srv.tlsApp = tlsApp @@ -120,6 +124,7 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error { continue } + // find all qualifying domain names, de-duplicated domainSet := make(map[string]struct{}) for _, route := range srv.Routes { for _, m := range route.matchers { @@ -133,21 +138,26 @@ func (hc *httpModuleConfig) automaticHTTPS(handle caddy2.Handle) error { } } } - var domains []string - for d := range domainSet { - domains = append(domains, d) - } - if len(domains) > 0 { + + if len(domainSet) > 0 { + // marshal the domains into a slice + var domains []string + for d := range domainSet { + domains = append(domains, d) + } + + // manage their certificates err := tlsApp.Manage(domains) if err != nil { return fmt.Errorf("%s: managing certificate for %s: %s", srvName, domains, err) } - // TODO: Connection policies... redirects... man... + + // tell the server to use TLS srv.TLSConnPolicies = caddytls.ConnectionPolicies{ - { - ALPN: defaultALPN, - }, + {ALPN: defaultALPN}, } + + // TODO: create HTTP->HTTPS redirects } } diff --git a/modules/caddytls/connpolicy.go b/modules/caddytls/connpolicy.go index 94000345..a085fa30 100644 --- a/modules/caddytls/connpolicy.go +++ b/modules/caddytls/connpolicy.go @@ -75,7 +75,11 @@ type ConnectionPolicy struct { } func (cp *ConnectionPolicy) buildStandardTLSConfig(handle caddy2.Handle) error { - tlsApp := handle.App("tls").(*TLS) + tlsAppIface, err := handle.App("tls") + if err != nil { + return fmt.Errorf("getting tls app: %v", err) + } + tlsApp := tlsAppIface.(*TLS) cfg := &tls.Config{ NextProtos: cp.ALPN,