From af25f0254e94eb2e2898ba495bfc3de209a49e79 Mon Sep 17 00:00:00 2001 From: Matthew Holt Date: Thu, 22 Aug 2019 13:38:37 -0600 Subject: caddyfile: Support global config block; allow non-empty blocks w/ 0 keys --- caddyconfig/httpcaddyfile/global.go | 53 +++++++++++++++++++++++++++++++++++ caddyconfig/httpcaddyfile/httptype.go | 53 +++++++++++++++++++++++++---------- 2 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 caddyconfig/httpcaddyfile/global.go (limited to 'caddyconfig/httpcaddyfile') diff --git a/caddyconfig/httpcaddyfile/global.go b/caddyconfig/httpcaddyfile/global.go new file mode 100644 index 0000000..067d06e --- /dev/null +++ b/caddyconfig/httpcaddyfile/global.go @@ -0,0 +1,53 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package httpcaddyfile + +import ( + "strconv" + + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" +) + +func parseHTTPPort(d *caddyfile.Dispenser) (int, error) { + var httpPort int + for d.Next() { + var httpPortStr string + if !d.AllArgs(&httpPortStr) { + return 0, d.ArgErr() + } + var err error + httpPort, err = strconv.Atoi(httpPortStr) + if err != nil { + return 0, d.Errf("converting port '%s' to integer value: %v", httpPortStr, err) + } + } + return httpPort, nil +} + +func parseHTTPSPort(d *caddyfile.Dispenser) (int, error) { + var httpsPort int + for d.Next() { + var httpsPortStr string + if !d.AllArgs(&httpsPortStr) { + return 0, d.ArgErr() + } + var err error + httpsPort, err = strconv.Atoi(httpsPortStr) + if err != nil { + return 0, d.Errf("converting port '%s' to integer value: %v", httpsPortStr, err) + } + } + return httpsPort, nil +} diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 00ce2cf..047d559 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -19,7 +19,6 @@ import ( "fmt" "reflect" "sort" - "strconv" "strings" "github.com/caddyserver/caddy/v2" @@ -44,7 +43,7 @@ type ServerType struct { // Setup makes a config from the tokens. func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, - options map[string]string) (*caddy.Config, []caddyconfig.Warning, error) { + options map[string]interface{}) (*caddy.Config, []caddyconfig.Warning, error) { var warnings []caddyconfig.Warning var serverBlocks []serverBlock @@ -55,6 +54,29 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, }) } + // global configuration + if len(serverBlocks) > 0 && len(serverBlocks[0].block.Keys) == 0 { + sb := serverBlocks[0] + for _, segment := range sb.block.Segments { + dir := segment.Directive() + var val interface{} + var err error + switch dir { + case "http_port": + val, err = parseHTTPPort(caddyfile.NewDispenser(segment)) + case "https_port": + val, err = parseHTTPSPort(caddyfile.NewDispenser(segment)) + default: + return nil, warnings, fmt.Errorf("unrecognized parameter name: %s", dir) + } + if err != nil { + return nil, warnings, fmt.Errorf("%s: %v", dir, err) + } + options[dir] = val + } + serverBlocks = serverBlocks[1:] + } + for _, sb := range serverBlocks { // replace shorthand placeholders (which are // convenient when writing a Caddyfile) with @@ -77,11 +99,15 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, } } + if len(sb.block.Keys) == 0 { + return nil, warnings, fmt.Errorf("server block without any key is global configuration, and if used, it must be first") + } + // extract matcher definitions d := sb.block.DispenseDirective("matcher") matcherDefs, err := st.parseMatcherDefinitions(d) if err != nil { - return nil, nil, err + return nil, warnings, err } for _, segment := range sb.block.Segments { @@ -129,8 +155,8 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock, // now that each server is configured, make the HTTP app httpApp := caddyhttp.App{ - HTTPPort: tryInt(options["http-port"], &warnings), - HTTPSPort: tryInt(options["https-port"], &warnings), + HTTPPort: tryInt(options["http_port"], &warnings), + HTTPSPort: tryInt(options["https_port"], &warnings), Servers: servers, } @@ -494,17 +520,14 @@ func encodeMatcherSet(matchers map[string]caddyhttp.RequestMatcher) (map[string] return msEncoded, nil } -// tryInt tries to convert str to an integer. If it fails, it downgrades -// the error to a warning and returns 0. -func tryInt(str string, warnings *[]caddyconfig.Warning) int { - if str == "" { - return 0 - } - val, err := strconv.Atoi(str) - if err != nil && warnings != nil { - *warnings = append(*warnings, caddyconfig.Warning{Message: err.Error()}) +// tryInt tries to convert val to an integer. If it fails, +// it downgrades the error to a warning and returns 0. +func tryInt(val interface{}, warnings *[]caddyconfig.Warning) int { + intVal, ok := val.(int) + if val != nil && !ok && warnings != nil { + *warnings = append(*warnings, caddyconfig.Warning{Message: "not an integer type"}) } - return val + return intVal } type matcherSetAndTokens struct { -- cgit v1.2.3