diff options
15 files changed, 1084 insertions, 658 deletions
diff --git a/caddyconfig/httpcaddyfile/addresses.go b/caddyconfig/httpcaddyfile/addresses.go index 51411a9..7105320 100644 --- a/caddyconfig/httpcaddyfile/addresses.go +++ b/caddyconfig/httpcaddyfile/addresses.go @@ -18,6 +18,7 @@ import ( "fmt" "net" "reflect" + "sort" "strconv" "strings" "unicode" @@ -163,6 +164,13 @@ func (st *ServerType) consolidateAddrMappings(addrToServerBlocks map[string][]se sbaddrs = append(sbaddrs, a) } + + // sort them by their first address (we know there will always be at least one) + // to avoid problems with non-deterministic ordering (makes tests flaky) + sort.Slice(sbaddrs, func(i, j int) bool { + return sbaddrs[i].addresses[0] < sbaddrs[j].addresses[0] + }) + return sbaddrs } diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 35eab90..e4e40b2 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -218,13 +218,6 @@ func (st ServerType) Setup(inputServerBlocks []caddyfile.ServerBlock, return nil, warnings, err } - // if experimental HTTP/3 is enabled, enable it on each server - if enableH3, ok := options["experimental_http3"].(bool); ok && enableH3 { - for _, srv := range httpApp.Servers { - srv.ExperimentalHTTP3 = true - } - } - // extract any custom logs, and enforce configured levels var customLogs []namedCustomLog var hasDefaultLog bool @@ -311,23 +304,54 @@ func (ServerType) evaluateGlobalOptionsBlock(serverBlocks []serverBlock, options } for _, segment := range serverBlocks[0].block.Segments { - dir := segment.Directive() + opt := segment.Directive() var val interface{} var err error disp := caddyfile.NewDispenser(segment) - dirFunc, ok := registeredGlobalOptions[dir] + optFunc, ok := registeredGlobalOptions[opt] if !ok { tkn := segment[0] - return nil, fmt.Errorf("%s:%d: unrecognized global option: %s", tkn.File, tkn.Line, dir) + return nil, fmt.Errorf("%s:%d: unrecognized global option: %s", tkn.File, tkn.Line, opt) } - val, err = dirFunc(disp) + val, err = optFunc(disp) if err != nil { - return nil, fmt.Errorf("parsing caddyfile tokens for '%s': %v", dir, err) + return nil, fmt.Errorf("parsing caddyfile tokens for '%s': %v", opt, err) + } + + // As a special case, fold multiple "servers" options together + // in an array instead of overwriting a possible existing value + if opt == "servers" { + existingOpts, ok := options[opt].([]serverOptions) + if !ok { + existingOpts = []serverOptions{} + } + serverOpts, ok := val.(serverOptions) + if !ok { + return nil, fmt.Errorf("unexpected type from 'servers' global options") + } + options[opt] = append(existingOpts, serverOpts) + continue } - options[dir] = val + options[opt] = val + } + + // If we got "servers" options, we'll sort them by their listener address + if serverOpts, ok := options["servers"].([]serverOptions); ok { + sort.Slice(serverOpts, func(i, j int) bool { + return len(serverOpts[i].ListenerAddress) > len(serverOpts[j].ListenerAddress) + }) + + // Reject the config if there are duplicate listener address + seen := make(map[string]bool) + for _, entry := range serverOpts { + if _, alreadySeen := seen[entry.ListenerAddress]; alreadySeen { + return nil, fmt.Errorf("cannot have 'servers' global options with duplicate listener addresses: %s", entry.ListenerAddress) + } + seen[entry.ListenerAddress] = true + } } return serverBlocks[1:], nil @@ -602,6 +626,11 @@ func (st *ServerType) serversFromPairings( servers[fmt.Sprintf("srv%d", i)] = srv } + err := applyServerOptions(servers, options, warnings) + if err != nil { + return nil, err + } + return servers, nil } diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go index 7d34805..5001974 100644 --- a/caddyconfig/httpcaddyfile/options.go +++ b/caddyconfig/httpcaddyfile/options.go @@ -43,6 +43,7 @@ func init() { RegisterGlobalOption("local_certs", parseOptTrue) RegisterGlobalOption("key_type", parseOptSingleString) RegisterGlobalOption("auto_https", parseOptAutoHTTPS) + RegisterGlobalOption("servers", parseServerOptions) } func parseOptTrue(d *caddyfile.Dispenser) (interface{}, error) { @@ -361,3 +362,7 @@ func parseOptAutoHTTPS(d *caddyfile.Dispenser) (interface{}, error) { } return val, nil } + +func parseServerOptions(d *caddyfile.Dispenser) (interface{}, error) { + return unmarshalCaddyfileServerOptions(d) +} diff --git a/caddyconfig/httpcaddyfile/serveroptions.go b/caddyconfig/httpcaddyfile/serveroptions.go new file mode 100644 index 0000000..38fa0f1 --- /dev/null +++ b/caddyconfig/httpcaddyfile/serveroptions.go @@ -0,0 +1,235 @@ +// 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 ( + "encoding/json" + "fmt" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/caddyserver/caddy/v2/modules/caddyhttp" + "github.com/dustin/go-humanize" +) + +// serverOptions collects server config overrides parsed from Caddyfile global options +type serverOptions struct { + // If set, will only apply these options to servers that contain a + // listener address that matches exactly. If empty, will apply to all + // servers that were not already matched by another serverOptions. + ListenerAddress string + + // These will all map 1:1 to the caddyhttp.Server struct + ListenerWrappersRaw []json.RawMessage + ReadTimeout caddy.Duration + ReadHeaderTimeout caddy.Duration + WriteTimeout caddy.Duration + IdleTimeout caddy.Duration + MaxHeaderBytes int + AllowH2C bool + ExperimentalHTTP3 bool + StrictSNIHost *bool +} + +func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (interface{}, error) { + serverOpts := serverOptions{} + for d.Next() { + if d.NextArg() { + serverOpts.ListenerAddress = d.Val() + if d.NextArg() { + return nil, d.ArgErr() + } + } + for nesting := d.Nesting(); d.NextBlock(nesting); { + switch d.Val() { + case "listener_wrappers": + for nesting := d.Nesting(); d.NextBlock(nesting); { + mod, err := caddy.GetModule("caddy.listeners." + d.Val()) + if err != nil { + return nil, fmt.Errorf("finding listener module '%s': %v", d.Val(), err) + } + unm, ok := mod.New().(caddyfile.Unmarshaler) + if !ok { + return nil, fmt.Errorf("listener module '%s' is not a Caddyfile unmarshaler", mod) + } + err = unm.UnmarshalCaddyfile(d.NewFromNextSegment()) + if err != nil { + return nil, err + } + listenerWrapper, ok := unm.(caddy.ListenerWrapper) + if !ok { + return nil, fmt.Errorf("module %s is not a listener wrapper", mod) + } + jsonListenerWrapper := caddyconfig.JSONModuleObject( + listenerWrapper, + "wrapper", + listenerWrapper.(caddy.Module).CaddyModule().ID.Name(), + nil, + ) + serverOpts.ListenerWrappersRaw = append(serverOpts.ListenerWrappersRaw, jsonListenerWrapper) + } + + case "timeouts": + for nesting := d.Nesting(); d.NextBlock(nesting); { + switch d.Val() { + case "read_body": + if !d.NextArg() { + return nil, d.ArgErr() + } + dur, err := caddy.ParseDuration(d.Val()) + if err != nil { + return nil, d.Errf("parsing read_body timeout duration: %v", err) + } + serverOpts.ReadTimeout = caddy.Duration(dur) + + case "read_header": + if !d.NextArg() { + return nil, d.ArgErr() + } + dur, err := caddy.ParseDuration(d.Val()) + if err != nil { + return nil, d.Errf("parsing read_header timeout duration: %v", err) + } + serverOpts.ReadHeaderTimeout = caddy.Duration(dur) + + case "write": + if !d.NextArg() { + return nil, d.ArgErr() + } + dur, err := caddy.ParseDuration(d.Val()) + if err != nil { + return nil, d.Errf("parsing write timeout duration: %v", err) + } + serverOpts.WriteTimeout = caddy.Duration(dur) + + case "idle": + if !d.NextArg() { + return nil, d.ArgErr() + } + dur, err := caddy.ParseDuration(d.Val()) + if err != nil { + return nil, d.Errf("parsing idle timeout duration: %v", err) + } + serverOpts.IdleTimeout = caddy.Duration(dur) + + default: + return nil, d.Errf("unrecognized timeouts option '%s'", d.Val()) + } + } + + case "max_header_size": + var sizeStr string + if !d.AllArgs(&sizeStr) { + return nil, d.ArgErr() + } + size, err := humanize.ParseBytes(sizeStr) + if err != nil { + return nil, d.Errf("parsing max_header_size: %v", err) + } + serverOpts.MaxHeaderBytes = int(size) + + case "protocol": + for nesting := d.Nesting(); d.NextBlock(nesting); { + switch d.Val() { + case "allow_h2c": + if d.NextArg() { + return nil, d.ArgErr() + } + serverOpts.AllowH2C = true + + case "experimental_http3": + if d.NextArg() { + return nil, d.ArgErr() + } + serverOpts.ExperimentalHTTP3 = true + + case "strict_sni_host": + if d.NextArg() { + return nil, d.ArgErr() + } + trueBool := true + serverOpts.StrictSNIHost = &trueBool + + default: + return nil, d.Errf("unrecognized protocol option '%s'", d.Val()) + } + } + + default: + return nil, d.Errf("unrecognized servers option '%s'", d.Val()) + } + } + } + return serverOpts, nil +} + +// applyServerOptions sets the server options on the appropriate servers +func applyServerOptions( + servers map[string]*caddyhttp.Server, + options map[string]interface{}, + warnings *[]caddyconfig.Warning, +) error { + // If experimental HTTP/3 is enabled, enable it on each server. + // We already know there won't be a conflict with serverOptions because + // we validated earlier that "experimental_http3" cannot be set at the same + // time as "servers" + if enableH3, ok := options["experimental_http3"].(bool); ok && enableH3 { + *warnings = append(*warnings, caddyconfig.Warning{Message: "the 'experimental_http3' global option is deprecated, please use the 'servers > protocol > experimental_http3' option instead"}) + for _, srv := range servers { + srv.ExperimentalHTTP3 = true + } + } + + serverOpts, ok := options["servers"].([]serverOptions) + if !ok { + return nil + } + + for _, server := range servers { + // find the options that apply to this server + opts := func() *serverOptions { + for _, entry := range serverOpts { + if entry.ListenerAddress == "" { + return &entry + } + for _, listener := range server.Listen { + if entry.ListenerAddress == listener { + return &entry + } + } + } + return nil + }() + + // if none apply, then move to the next server + if opts == nil { + continue + } + + // set all the options + server.ListenerWrappersRaw = opts.ListenerWrappersRaw + server.ReadTimeout = opts.ReadTimeout + server.ReadHeaderTimeout = opts.ReadHeaderTimeout + server.WriteTimeout = opts.WriteTimeout + server.IdleTimeout = opts.IdleTimeout + server.MaxHeaderBytes = opts.MaxHeaderBytes + server.AllowH2C = opts.AllowH2C + server.ExperimentalHTTP3 = opts.ExperimentalHTTP3 + server.StrictSNIHost = opts.StrictSNIHost + } + + return nil +} diff --git a/caddytest/integration/caddyfile_adapt/global_server_options_multi.txt b/caddytest/integration/caddyfile_adapt/global_server_options_multi.txt new file mode 100644 index 0000000..653eee5 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/global_server_options_multi.txt @@ -0,0 +1,83 @@ +{ + servers { + timeouts { + idle 90s + } + } + servers :80 { + timeouts { + idle 60s + } + } + servers :443 { + timeouts { + idle 30s + } + } +} + +foo.com { +} + +http://bar.com { +} + +:8080 { +} + +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "idle_timeout": 30000000000, + "routes": [ + { + "match": [ + { + "host": [ + "foo.com" + ] + } + ], + "terminal": true + } + ] + }, + "srv1": { + "listen": [ + ":80" + ], + "idle_timeout": 60000000000, + "routes": [ + { + "match": [ + { + "host": [ + "bar.com" + ] + } + ], + "terminal": true + } + ], + "automatic_https": { + "skip": [ + "bar.com" + ] + } + }, + "srv2": { + "listen": [ + ":8080" + ], + "idle_timeout": 90000000000 + } + } + } + } +} diff --git a/caddytest/integration/caddyfile_adapt/global_server_options_single.txt b/caddytest/integration/caddyfile_adapt/global_server_options_single.txt new file mode 100644 index 0000000..5a5c64c --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/global_server_options_single.txt @@ -0,0 +1,62 @@ +{ + servers { + listener_wrappers { + tls + } + timeouts { + read_body 30s + read_header 30s + write 30s + idle 30s + } + max_header_size 100MB + protocol { + allow_h2c + experimental_http3 + strict_sni_host + } + } +} + +foo.com { +} + +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "listener_wrappers": [ + { + "wrapper": "tls" + } + ], + "read_timeout": 30000000000, + "read_header_timeout": 30000000000, + "write_timeout": 30000000000, + "idle_timeout": 30000000000, + "max_header_bytes": 100000000, + "routes": [ + { + "match": [ + { + "host": [ + "foo.com" + ] + } + ], + "terminal": true + } + ], + "strict_sni_host": true, + "experimental_http3": true, + "allow_h2c": true + } + } + } + } +}
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/handle_path.txt b/caddytest/integration/caddyfile_adapt/handle_path.txt index 7f40fcf..f881743 100644 --- a/caddytest/integration/caddyfile_adapt/handle_path.txt +++ b/caddytest/integration/caddyfile_adapt/handle_path.txt @@ -1,52 +1,52 @@ -:80
-handle_path /api/v1/* {
- respond "API v1"
-}
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":80"
- ],
- "routes": [
- {
- "match": [
- {
- "path": [
- "/api/v1/*"
- ]
- }
- ],
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "handler": "rewrite",
- "strip_path_prefix": "/api/v1"
- }
- ]
- },
- {
- "handle": [
- {
- "body": "API v1",
- "handler": "static_response"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
+:80 +handle_path /api/v1/* { + respond "API v1" +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "path": [ + "/api/v1/*" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "rewrite", + "strip_path_prefix": "/api/v1" + } + ] + }, + { + "handle": [ + { + "body": "API v1", + "handler": "static_response" + } + ] + } + ] + } + ] + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/handle_path_sorting.txt b/caddytest/integration/caddyfile_adapt/handle_path_sorting.txt index 3258dc9..0a89f2a 100644 --- a/caddytest/integration/caddyfile_adapt/handle_path_sorting.txt +++ b/caddytest/integration/caddyfile_adapt/handle_path_sorting.txt @@ -1,105 +1,105 @@ -:80 {
- handle /api/* {
- respond "api"
- }
-
- handle_path /static/* {
- respond "static"
- }
-
- handle {
- respond "handle"
- }
-}
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":80"
- ],
- "routes": [
- {
- "group": "group3",
- "match": [
- {
- "path": [
- "/static/*"
- ]
- }
- ],
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "handler": "rewrite",
- "strip_path_prefix": "/static"
- }
- ]
- },
- {
- "handle": [
- {
- "body": "static",
- "handler": "static_response"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "group": "group3",
- "match": [
- {
- "path": [
- "/api/*"
- ]
- }
- ],
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "body": "api",
- "handler": "static_response"
- }
- ]
- }
- ]
- }
- ]
- },
- {
- "group": "group3",
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "body": "handle",
- "handler": "static_response"
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
+:80 { + handle /api/* { + respond "api" + } + + handle_path /static/* { + respond "static" + } + + handle { + respond "handle" + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "group": "group3", + "match": [ + { + "path": [ + "/static/*" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "rewrite", + "strip_path_prefix": "/static" + } + ] + }, + { + "handle": [ + { + "body": "static", + "handler": "static_response" + } + ] + } + ] + } + ] + }, + { + "group": "group3", + "match": [ + { + "path": [ + "/api/*" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "api", + "handler": "static_response" + } + ] + } + ] + } + ] + }, + { + "group": "group3", + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "handle", + "handler": "static_response" + } + ] + } + ] + } + ] + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/import_args_file.txt b/caddytest/integration/caddyfile_adapt/import_args_file.txt index 6947f68..1eb78f1 100644 --- a/caddytest/integration/caddyfile_adapt/import_args_file.txt +++ b/caddytest/integration/caddyfile_adapt/import_args_file.txt @@ -1,49 +1,49 @@ -example.com
-
-import testdata/import_respond.txt Groot Rocket
-import testdata/import_respond.txt you "the confused man"
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":443"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "example.com"
- ]
- }
- ],
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "body": "'I am Groot', hears Rocket",
- "handler": "static_response"
- },
- {
- "body": "'I am you', hears the confused man",
- "handler": "static_response"
- }
- ]
- }
- ]
- }
- ],
- "terminal": true
- }
- ]
- }
- }
- }
- }
+example.com + +import testdata/import_respond.txt Groot Rocket +import testdata/import_respond.txt you "the confused man" +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "routes": [ + { + "match": [ + { + "host": [ + "example.com" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "body": "'I am Groot', hears Rocket", + "handler": "static_response" + }, + { + "body": "'I am you', hears the confused man", + "handler": "static_response" + } + ] + } + ] + } + ], + "terminal": true + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/import_args_snippet.txt b/caddytest/integration/caddyfile_adapt/import_args_snippet.txt index 8d2ff34..9fce9ab 100644 --- a/caddytest/integration/caddyfile_adapt/import_args_snippet.txt +++ b/caddytest/integration/caddyfile_adapt/import_args_snippet.txt @@ -1,83 +1,83 @@ -(logging) {
- log {
- output file /var/log/caddy/{args.0}.access.log
- }
-}
-
-a.example.com {
- import logging a.example.com
-}
-
-b.example.com {
- import logging b.example.com
-}
-----------
-{
- "logging": {
- "logs": {
- "default": {
- "exclude": [
- "http.log.access.log0",
- "http.log.access.log1"
- ]
- },
- "log0": {
- "writer": {
- "filename": "/var/log/caddy/a.example.com.access.log",
- "output": "file"
- },
- "include": [
- "http.log.access.log0"
- ]
- },
- "log1": {
- "writer": {
- "filename": "/var/log/caddy/b.example.com.access.log",
- "output": "file"
- },
- "include": [
- "http.log.access.log1"
- ]
- }
- }
- },
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":443"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "a.example.com"
- ]
- }
- ],
- "terminal": true
- },
- {
- "match": [
- {
- "host": [
- "b.example.com"
- ]
- }
- ],
- "terminal": true
- }
- ],
- "logs": {
- "logger_names": {
- "a.example.com": "log0",
- "b.example.com": "log1"
- }
- }
- }
- }
- }
- }
+(logging) { + log { + output file /var/log/caddy/{args.0}.access.log + } +} + +a.example.com { + import logging a.example.com +} + +b.example.com { + import logging b.example.com +} +---------- +{ + "logging": { + "logs": { + "default": { + "exclude": [ + "http.log.access.log0", + "http.log.access.log1" + ] + }, + "log0": { + "writer": { + "filename": "/var/log/caddy/a.example.com.access.log", + "output": "file" + }, + "include": [ + "http.log.access.log0" + ] + }, + "log1": { + "writer": { + "filename": "/var/log/caddy/b.example.com.access.log", + "output": "file" + }, + "include": [ + "http.log.access.log1" + ] + } + } + }, + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":443" + ], + "routes": [ + { + "match": [ + { + "host": [ + "a.example.com" + ] + } + ], + "terminal": true + }, + { + "match": [ + { + "host": [ + "b.example.com" + ] + } + ], + "terminal": true + } + ], + "logs": { + "logger_names": { + "a.example.com": "log0", + "b.example.com": "log1" + } + } + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/log_filters.txt b/caddytest/integration/caddyfile_adapt/log_filters.txt index 549f4e6..ab11807 100644 --- a/caddytest/integration/caddyfile_adapt/log_filters.txt +++ b/caddytest/integration/caddyfile_adapt/log_filters.txt @@ -1,69 +1,69 @@ -:80
-
-log {
- output stdout
- format filter {
- wrap console
- fields {
- request>headers>Authorization delete
- request>headers>Server delete
- request>remote_addr ip_mask {
- ipv4 24
- ipv6 32
- }
- }
- }
-}
-----------
-{
- "logging": {
- "logs": {
- "default": {
- "exclude": [
- "http.log.access.log0"
- ]
- },
- "log0": {
- "writer": {
- "output": "stdout"
- },
- "encoder": {
- "fields": {
- "request\u003eheaders\u003eAuthorization": {
- "filter": "delete"
- },
- "request\u003eheaders\u003eServer": {
- "filter": "delete"
- },
- "request\u003eremote_addr": {
- "filter": "ip_mask",
- "ipv4_cidr": 24,
- "ipv6_cidr": 32
- }
- },
- "format": "filter",
- "wrap": {
- "format": "console"
- }
- },
- "include": [
- "http.log.access.log0"
- ]
- }
- }
- },
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":80"
- ],
- "logs": {
- "default_logger_name": "log0"
- }
- }
- }
- }
- }
+:80 + +log { + output stdout + format filter { + wrap console + fields { + request>headers>Authorization delete + request>headers>Server delete + request>remote_addr ip_mask { + ipv4 24 + ipv6 32 + } + } + } +} +---------- +{ + "logging": { + "logs": { + "default": { + "exclude": [ + "http.log.access.log0" + ] + }, + "log0": { + "writer": { + "output": "stdout" + }, + "encoder": { + "fields": { + "request\u003eheaders\u003eAuthorization": { + "filter": "delete" + }, + "request\u003eheaders\u003eServer": { + "filter": "delete" + }, + "request\u003eremote_addr": { + "filter": "ip_mask", + "ipv4_cidr": 24, + "ipv6_cidr": 32 + } + }, + "format": "filter", + "wrap": { + "format": "console" + } + }, + "include": [ + "http.log.access.log0" + ] + } + } + }, + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "logs": { + "default_logger_name": "log0" + } + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt b/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt index d453128..bb7c7f7 100644 --- a/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt +++ b/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt @@ -1,132 +1,132 @@ -:8886
-
-route {
- # Add trailing slash for directory requests
- @canonicalPath {
- file {
- try_files {path}/index.php
- }
- not path */
- }
- redir @canonicalPath {path}/ 308
-
- # If the requested file does not exist, try index files
- @indexFiles {
- file {
- try_files {path} {path}/index.php index.php
- split_path .php
- }
- }
- rewrite @indexFiles {http.matchers.file.relative}
-
- # Proxy PHP files to the FastCGI responder
- @phpFiles {
- path *.php
- }
- reverse_proxy @phpFiles 127.0.0.1:9000 {
- transport fastcgi {
- split .php
- }
- }
-}
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8886"
- ],
- "routes": [
- {
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "handler": "static_response",
- "headers": {
- "Location": [
- "{http.request.uri.path}/"
- ]
- },
- "status_code": 308
- }
- ],
- "match": [
- {
- "file": {
- "try_files": [
- "{http.request.uri.path}/index.php"
- ]
- },
- "not": [
- {
- "path": [
- "*/"
- ]
- }
- ]
- }
- ]
- },
- {
- "handle": [
- {
- "handler": "rewrite",
- "uri": "{http.matchers.file.relative}"
- }
- ],
- "match": [
- {
- "file": {
- "split_path": [
- ".php"
- ],
- "try_files": [
- "{http.request.uri.path}",
- "{http.request.uri.path}/index.php",
- "index.php"
- ]
- }
- }
- ]
- },
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "transport": {
- "protocol": "fastcgi",
- "split_path": [
- ".php"
- ]
- },
- "upstreams": [
- {
- "dial": "127.0.0.1:9000"
- }
- ]
- }
- ],
- "match": [
- {
- "path": [
- "*.php"
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
+:8886 + +route { + # Add trailing slash for directory requests + @canonicalPath { + file { + try_files {path}/index.php + } + not path */ + } + redir @canonicalPath {path}/ 308 + + # If the requested file does not exist, try index files + @indexFiles { + file { + try_files {path} {path}/index.php index.php + split_path .php + } + } + rewrite @indexFiles {http.matchers.file.relative} + + # Proxy PHP files to the FastCGI responder + @phpFiles { + path *.php + } + reverse_proxy @phpFiles 127.0.0.1:9000 { + transport fastcgi { + split .php + } + } +} +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":8886" + ], + "routes": [ + { + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "static_response", + "headers": { + "Location": [ + "{http.request.uri.path}/" + ] + }, + "status_code": 308 + } + ], + "match": [ + { + "file": { + "try_files": [ + "{http.request.uri.path}/index.php" + ] + }, + "not": [ + { + "path": [ + "*/" + ] + } + ] + } + ] + }, + { + "handle": [ + { + "handler": "rewrite", + "uri": "{http.matchers.file.relative}" + } + ], + "match": [ + { + "file": { + "split_path": [ + ".php" + ], + "try_files": [ + "{http.request.uri.path}", + "{http.request.uri.path}/index.php", + "index.php" + ] + } + } + ] + }, + { + "handle": [ + { + "handler": "reverse_proxy", + "transport": { + "protocol": "fastcgi", + "split_path": [ + ".php" + ] + }, + "upstreams": [ + { + "dial": "127.0.0.1:9000" + } + ] + } + ], + "match": [ + { + "path": [ + "*.php" + ] + } + ] + } + ] + } + ] + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/php_fastcgi_matcher.txt b/caddytest/integration/caddyfile_adapt/php_fastcgi_matcher.txt index 2f4e6fe..488c525 100644 --- a/caddytest/integration/caddyfile_adapt/php_fastcgi_matcher.txt +++ b/caddytest/integration/caddyfile_adapt/php_fastcgi_matcher.txt @@ -1,112 +1,112 @@ -:8884
-
-@api host example.com
-php_fastcgi @api localhost:9000
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":8884"
- ],
- "routes": [
- {
- "match": [
- {
- "host": [
- "example.com"
- ]
- }
- ],
- "handle": [
- {
- "handler": "subroute",
- "routes": [
- {
- "handle": [
- {
- "handler": "static_response",
- "headers": {
- "Location": [
- "{http.request.uri.path}/"
- ]
- },
- "status_code": 308
- }
- ],
- "match": [
- {
- "file": {
- "try_files": [
- "{http.request.uri.path}/index.php"
- ]
- },
- "not": [
- {
- "path": [
- "*/"
- ]
- }
- ]
- }
- ]
- },
- {
- "handle": [
- {
- "handler": "rewrite",
- "uri": "{http.matchers.file.relative}"
- }
- ],
- "match": [
- {
- "file": {
- "split_path": [
- ".php"
- ],
- "try_files": [
- "{http.request.uri.path}",
- "{http.request.uri.path}/index.php",
- "index.php"
- ]
- }
- }
- ]
- },
- {
- "handle": [
- {
- "handler": "reverse_proxy",
- "transport": {
- "protocol": "fastcgi",
- "split_path": [
- ".php"
- ]
- },
- "upstreams": [
- {
- "dial": "localhost:9000"
- }
- ]
- }
- ],
- "match": [
- {
- "path": [
- "*.php"
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- }
- }
- }
+:8884 + +@api host example.com +php_fastcgi @api localhost:9000 +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":8884" + ], + "routes": [ + { + "match": [ + { + "host": [ + "example.com" + ] + } + ], + "handle": [ + { + "handler": "subroute", + "routes": [ + { + "handle": [ + { + "handler": "static_response", + "headers": { + "Location": [ + "{http.request.uri.path}/" + ] + }, + "status_code": 308 + } + ], + "match": [ + { + "file": { + "try_files": [ + "{http.request.uri.path}/index.php" + ] + }, + "not": [ + { + "path": [ + "*/" + ] + } + ] + } + ] + }, + { + "handle": [ + { + "handler": "rewrite", + "uri": "{http.matchers.file.relative}" + } + ], + "match": [ + { + "file": { + "split_path": [ + ".php" + ], + "try_files": [ + "{http.request.uri.path}", + "{http.request.uri.path}/index.php", + "index.php" + ] + } + } + ] + }, + { + "handle": [ + { + "handler": "reverse_proxy", + "transport": { + "protocol": "fastcgi", + "split_path": [ + ".php" + ] + }, + "upstreams": [ + { + "dial": "localhost:9000" + } + ] + } + ], + "match": [ + { + "path": [ + "*.php" + ] + } + ] + } + ] + } + ] + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/caddytest/integration/caddyfile_adapt/sort_directives_with_any_matcher_first.txt b/caddytest/integration/caddyfile_adapt/sort_directives_with_any_matcher_first.txt index 6203a89..3859a7e 100644 --- a/caddytest/integration/caddyfile_adapt/sort_directives_with_any_matcher_first.txt +++ b/caddytest/integration/caddyfile_adapt/sort_directives_with_any_matcher_first.txt @@ -1,51 +1,51 @@ -:80
-
-respond 200
-
-@untrusted not remote_ip 10.1.1.0/24
-respond @untrusted 401
-----------
-{
- "apps": {
- "http": {
- "servers": {
- "srv0": {
- "listen": [
- ":80"
- ],
- "routes": [
- {
- "match": [
- {
- "not": [
- {
- "remote_ip": {
- "ranges": [
- "10.1.1.0/24"
- ]
- }
- }
- ]
- }
- ],
- "handle": [
- {
- "handler": "static_response",
- "status_code": 401
- }
- ]
- },
- {
- "handle": [
- {
- "handler": "static_response",
- "status_code": 200
- }
- ]
- }
- ]
- }
- }
- }
- }
+:80 + +respond 200 + +@untrusted not remote_ip 10.1.1.0/24 +respond @untrusted 401 +---------- +{ + "apps": { + "http": { + "servers": { + "srv0": { + "listen": [ + ":80" + ], + "routes": [ + { + "match": [ + { + "not": [ + { + "remote_ip": { + "ranges": [ + "10.1.1.0/24" + ] + } + } + ] + } + ], + "handle": [ + { + "handler": "static_response", + "status_code": 401 + } + ] + }, + { + "handle": [ + { + "handler": "static_response", + "status_code": 200 + } + ] + } + ] + } + } + } + } }
\ No newline at end of file diff --git a/modules/caddyhttp/caddyhttp.go b/modules/caddyhttp/caddyhttp.go index 485afe0..d93a5c8 100644 --- a/modules/caddyhttp/caddyhttp.go +++ b/modules/caddyhttp/caddyhttp.go @@ -23,6 +23,7 @@ import ( "strconv" "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" ) func init() { @@ -231,6 +232,8 @@ func (tlsPlaceholderWrapper) CaddyModule() caddy.ModuleInfo { func (tlsPlaceholderWrapper) WrapListener(ln net.Listener) net.Listener { return ln } +func (tlsPlaceholderWrapper) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { return nil } + const ( // DefaultHTTPPort is the default port for HTTP. DefaultHTTPPort = 80 @@ -241,3 +244,4 @@ const ( // Interface guard var _ caddy.ListenerWrapper = (*tlsPlaceholderWrapper)(nil) +var _ caddyfile.Unmarshaler = (*tlsPlaceholderWrapper)(nil) |