diff options
Diffstat (limited to 'caddyconfig/httpcaddyfile/builtins.go')
-rw-r--r-- | caddyconfig/httpcaddyfile/builtins.go | 356 |
1 files changed, 177 insertions, 179 deletions
diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index 7e51e46..0fdfcd5 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -19,239 +19,237 @@ import ( "fmt" "html" "net/http" + "reflect" - "github.com/caddyserver/caddy/v2/caddyconfig" - "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/caddyserver/caddy/v2/modules/caddyhttp" + "github.com/caddyserver/caddy/caddyconfig" + "github.com/caddyserver/caddy/modules/caddyhttp" "github.com/caddyserver/caddy/v2/modules/caddytls" ) -func (st *ServerType) parseRoot( - tkns []caddyfile.Token, - matcherDefs map[string]map[string]json.RawMessage, - warnings *[]caddyconfig.Warning, -) ([]caddyhttp.Route, error) { - var routes []caddyhttp.Route - - matchersAndTokens, err := st.tokensToMatcherSets(tkns, matcherDefs, warnings) - if err != nil { - return nil, err - } - - for _, mst := range matchersAndTokens { - d := caddyfile.NewDispenser("Caddyfile", mst.tokens) - - var root string - for d.Next() { - if !d.NextArg() { - return nil, d.ArgErr() - } - root = d.Val() - if d.NextArg() { - return nil, d.ArgErr() - } - } - - varsHandler := caddyhttp.VarsMiddleware{"root": root} - route := caddyhttp.Route{ - Handle: []json.RawMessage{ - caddyconfig.JSONModuleObject(varsHandler, "handler", "vars", warnings), - }, - } - if mst.matcherSet != nil { - route.MatcherSets = []map[string]json.RawMessage{mst.matcherSet} - } +func init() { + RegisterDirective("bind", parseBind) + RegisterDirective("root", parseRoot) + RegisterDirective("tls", parseTLS) + RegisterHandlerDirective("redir", parseRedir) +} - routes = append(routes, route) +func parseBind(h Helper) ([]ConfigValue, error) { + var lnHosts []string + for h.Next() { + lnHosts = append(lnHosts, h.RemainingArgs()...) } - - return routes, nil + return h.NewBindAddresses(lnHosts), nil } -func (st *ServerType) parseRedir( - tkns []caddyfile.Token, - matcherDefs map[string]map[string]json.RawMessage, - warnings *[]caddyconfig.Warning, -) ([]caddyhttp.Route, error) { - var routes []caddyhttp.Route +func parseRoot(h Helper) ([]ConfigValue, error) { + if !h.Next() { + return nil, h.ArgErr() + } - matchersAndTokens, err := st.tokensToMatcherSets(tkns, matcherDefs, warnings) + matcherSet, ok, err := h.MatcherToken() if err != nil { return nil, err } - - for _, mst := range matchersAndTokens { - var route caddyhttp.Route - - d := caddyfile.NewDispenser("Caddyfile", mst.tokens) - - for d.Next() { - if !d.NextArg() { - return nil, d.ArgErr() - } - to := d.Val() - - var code string - if d.NextArg() { - code = d.Val() - } - if code == "permanent" { - code = "301" - } - if code == "temporary" || code == "" { - code = "307" - } - var body string - if code == "meta" { - // Script tag comes first since that will better imitate a redirect in the browser's - // history, but the meta tag is a fallback for most non-JS clients. - const metaRedir = `<!DOCTYPE html> -<html> - <head> - <title>Redirecting...</title> - <script>window.location.replace("%s");</script> - <meta http-equiv="refresh" content="0; URL='%s'"> - </head> - <body>Redirecting to <a href="%s">%s</a>...</body> -</html> -` - safeTo := html.EscapeString(to) - body = fmt.Sprintf(metaRedir, safeTo, safeTo, safeTo, safeTo) - } - - handler := caddyhttp.StaticResponse{ - StatusCode: caddyhttp.WeakString(code), - Headers: http.Header{"Location": []string{to}}, - Body: body, - } - - route.Handle = append(route.Handle, - caddyconfig.JSONModuleObject(handler, "handler", "static_response", warnings)) - } - - if mst.matcherSet != nil { - route.MatcherSets = []map[string]json.RawMessage{mst.matcherSet} - } - - routes = append(routes, route) + if !ok { + // no matcher token; oops + h.Dispenser.Prev() } - return routes, nil -} - -func (st *ServerType) parseTLSAutomationManager(d *caddyfile.Dispenser) (caddytls.ACMEManagerMaker, error) { - var m caddytls.ACMEManagerMaker - - for d.Next() { - firstLine := d.RemainingArgs() - if len(firstLine) == 1 && firstLine[0] != "off" { - m.Email = firstLine[0] - } - - var hasBlock bool - for d.NextBlock() { - hasBlock = true - switch d.Val() { - case "ca": - arg := d.RemainingArgs() - if len(arg) != 1 { - return m, d.ArgErr() - } - m.CA = arg[0] - // TODO: other properties - } - } + if !h.NextArg() { + return nil, h.ArgErr() + } + root := h.Val() + if h.NextArg() { + return nil, h.ArgErr() + } - // a naked tls directive is not allowed - if len(firstLine) == 0 && !hasBlock { - return m, d.ArgErr() - } + varsHandler := caddyhttp.VarsMiddleware{"root": root} + route := caddyhttp.Route{ + HandlersRaw: []json.RawMessage{ + caddyconfig.JSONModuleObject(varsHandler, "handler", "vars", nil), + }, + } + if matcherSet != nil { + route.MatcherSetsRaw = []map[string]json.RawMessage{matcherSet} } - return m, nil + return h.NewVarsRoute(route), nil } -func (st *ServerType) parseTLSCerts(d *caddyfile.Dispenser) (map[string]caddytls.CertificateLoader, error) { +func parseTLS(h Helper) ([]ConfigValue, error) { + var configVals []ConfigValue + + cp := new(caddytls.ConnectionPolicy) var fileLoader caddytls.FileLoader var folderLoader caddytls.FolderLoader - - for d.Next() { - // file loader - firstLine := d.RemainingArgs() - if len(firstLine) == 2 { + var mgr caddytls.ACMEManagerMaker + var off bool + + for h.Next() { + // file certificate loader + firstLine := h.RemainingArgs() + switch len(firstLine) { + case 0: + case 1: + if firstLine[0] == "off" { + off = true + } else { + mgr.Email = firstLine[0] + } + case 2: fileLoader = append(fileLoader, caddytls.CertKeyFilePair{ Certificate: firstLine[0], Key: firstLine[1], - // TODO: tags, for enterprise module's certificate selection + // TODO: add tags, for enterprise module's certificate selection }) + default: + return nil, h.ArgErr() } - // folder loader - for d.NextBlock() { - if d.Val() == "load" { - folderLoader = append(folderLoader, d.RemainingArgs()...) - } - } - } - - // put configured loaders into the map - loaders := make(map[string]caddytls.CertificateLoader) - if len(fileLoader) > 0 { - loaders["load_files"] = fileLoader - } - if len(folderLoader) > 0 { - loaders["load_folders"] = folderLoader - } - - return loaders, nil -} + var hasBlock bool + for h.NextBlock() { + hasBlock = true -func (st *ServerType) parseTLSConnPolicy(d *caddyfile.Dispenser) (*caddytls.ConnectionPolicy, error) { - cp := new(caddytls.ConnectionPolicy) + switch h.Val() { - for d.Next() { - for d.NextBlock() { - switch d.Val() { + // connection policy case "protocols": - args := d.RemainingArgs() + args := h.RemainingArgs() if len(args) == 0 { - return nil, d.SyntaxErr("one or two protocols") + return nil, h.SyntaxErr("one or two protocols") } if len(args) > 0 { if _, ok := caddytls.SupportedProtocols[args[0]]; !ok { - return nil, d.Errf("Wrong protocol name or protocol not supported: '%s'", args[0]) + return nil, h.Errf("Wrong protocol name or protocol not supported: '%s'", args[0]) } cp.ProtocolMin = args[0] } if len(args) > 1 { if _, ok := caddytls.SupportedProtocols[args[1]]; !ok { - return nil, d.Errf("Wrong protocol name or protocol not supported: '%s'", args[1]) + return nil, h.Errf("Wrong protocol name or protocol not supported: '%s'", args[1]) } cp.ProtocolMax = args[1] } case "ciphers": - for d.NextArg() { - if _, ok := caddytls.SupportedCipherSuites[d.Val()]; !ok { - return nil, d.Errf("Wrong cipher suite name or cipher suite not supported: '%s'", d.Val()) + for h.NextArg() { + if _, ok := caddytls.SupportedCipherSuites[h.Val()]; !ok { + return nil, h.Errf("Wrong cipher suite name or cipher suite not supported: '%s'", h.Val()) } - cp.CipherSuites = append(cp.CipherSuites, d.Val()) + cp.CipherSuites = append(cp.CipherSuites, h.Val()) } case "curves": - for d.NextArg() { - if _, ok := caddytls.SupportedCurves[d.Val()]; !ok { - return nil, d.Errf("Wrong curve name or curve not supported: '%s'", d.Val()) + for h.NextArg() { + if _, ok := caddytls.SupportedCurves[h.Val()]; !ok { + return nil, h.Errf("Wrong curve name or curve not supported: '%s'", h.Val()) } - cp.Curves = append(cp.Curves, d.Val()) + cp.Curves = append(cp.Curves, h.Val()) } case "alpn": - args := d.RemainingArgs() + args := h.RemainingArgs() if len(args) == 0 { - return nil, d.ArgErr() + return nil, h.ArgErr() } cp.ALPN = args + + // certificate folder loader + case "load": + folderLoader = append(folderLoader, h.RemainingArgs()...) + + // automation policy + case "ca": + arg := h.RemainingArgs() + if len(arg) != 1 { + return nil, h.ArgErr() + } + mgr.CA = arg[0] + + // TODO: other properties for automation manager } } + + // a naked tls directive is not allowed + if len(firstLine) == 0 && !hasBlock { + return nil, h.ArgErr() + } + } + + // connection policy + configVals = append(configVals, ConfigValue{ + Class: "tls.connection_policy", + Value: cp, + }) + + // certificate loaders + if len(fileLoader) > 0 { + configVals = append(configVals, ConfigValue{ + Class: "tls.certificate_loader", + Value: fileLoader, + }) + } + if len(folderLoader) > 0 { + configVals = append(configVals, ConfigValue{ + Class: "tls.certificate_loader", + Value: folderLoader, + }) + } + + // automation policy + if off { + configVals = append(configVals, ConfigValue{ + Class: "tls.off", + Value: true, + }) + } else if !reflect.DeepEqual(mgr, caddytls.ACMEManagerMaker{}) { + configVals = append(configVals, ConfigValue{ + Class: "tls.automation_manager", + Value: mgr, + }) + } + + return configVals, nil +} + +func parseRedir(h Helper) (caddyhttp.MiddlewareHandler, error) { + if !h.Next() { + return nil, h.ArgErr() + } + + if !h.NextArg() { + return nil, h.ArgErr() + } + to := h.Val() + + var code string + if h.NextArg() { + code = h.Val() + } + if code == "permanent" { + code = "301" + } + if code == "temporary" || code == "" { + code = "307" + } + var body string + if code == "meta" { + // Script tag comes first since that will better imitate a redirect in the browser's + // history, but the meta tag is a fallback for most non-JS clients. + const metaRedir = `<!DOCTYPE html> +<html> + <head> + <title>Redirecting...</title> + <script>window.location.replace("%s");</script> + <meta http-equiv="refresh" content="0; URL='%s'"> + </head> + <body>Redirecting to <a href="%s">%s</a>...</body> +</html> +` + safeTo := html.EscapeString(to) + body = fmt.Sprintf(metaRedir, safeTo, safeTo, safeTo, safeTo) } - return cp, nil + return caddyhttp.StaticResponse{ + StatusCode: caddyhttp.WeakString(code), + Headers: http.Header{"Location": []string{to}}, + Body: body, + }, nil } |