From 584eba94a4e06af9ce7efc91fb914f84d7a6a48c Mon Sep 17 00:00:00 2001 From: Francis Lavoie Date: Wed, 5 Aug 2020 15:42:29 -0400 Subject: httpcaddyfile: Allow named matchers in `route` blocks (#3632) --- caddyconfig/httpcaddyfile/builtins.go | 45 +++---- caddyconfig/httpcaddyfile/directives.go | 14 ++- .../caddyfile_adapt/php_fastcgi_expanded_form.txt | 132 +++++++++++++++++++++ 3 files changed, 161 insertions(+), 30 deletions(-) create mode 100644 caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go index 5dbb406..520796d 100644 --- a/caddyconfig/httpcaddyfile/builtins.go +++ b/caddyconfig/httpcaddyfile/builtins.go @@ -480,36 +480,23 @@ func parseRespond(h Helper) (caddyhttp.MiddlewareHandler, error) { func parseRoute(h Helper) (caddyhttp.MiddlewareHandler, error) { sr := new(caddyhttp.Subroute) - for h.Next() { - for nesting := h.Nesting(); h.NextBlock(nesting); { - dir := h.Val() - - dirFunc, ok := registeredDirectives[dir] - if !ok { - return nil, h.Errf("unrecognized directive: %s", dir) - } - - subHelper := h - subHelper.Dispenser = h.NewFromNextSegment() + allResults, err := parseSegmentAsConfig(h) + if err != nil { + return nil, err + } - results, err := dirFunc(subHelper) - if err != nil { - return nil, h.Errf("parsing caddyfile tokens for '%s': %v", dir, err) - } - for _, result := range results { - switch handler := result.Value.(type) { - case caddyhttp.Route: - sr.Routes = append(sr.Routes, handler) - case caddyhttp.Subroute: - // directives which return a literal subroute instead of a route - // means they intend to keep those handlers together without - // them being reordered; we're doing that anyway since we're in - // the route directive, so just append its handlers - sr.Routes = append(sr.Routes, handler.Routes...) - default: - return nil, h.Errf("%s directive returned something other than an HTTP route or subroute: %#v (only handler directives can be used in routes)", dir, result.Value) - } - } + for _, result := range allResults { + switch handler := result.Value.(type) { + case caddyhttp.Route: + sr.Routes = append(sr.Routes, handler) + case caddyhttp.Subroute: + // directives which return a literal subroute instead of a route + // means they intend to keep those handlers together without + // them being reordered; we're doing that anyway since we're in + // the route directive, so just append its handlers + sr.Routes = append(sr.Routes, handler.Routes...) + default: + return nil, h.Errf("%s directive returned something other than an HTTP route or subroute: %#v (only handler directives can be used in routes)", result.directive, result.Value) } } diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go index c31bdd3..e93fdd0 100644 --- a/caddyconfig/httpcaddyfile/directives.go +++ b/caddyconfig/httpcaddyfile/directives.go @@ -269,6 +269,18 @@ func (h Helper) NewBindAddresses(addrs []string) []ConfigValue { // are themselves treated as directives, from which a subroute is built // and returned. func ParseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) { + allResults, err := parseSegmentAsConfig(h) + if err != nil { + return nil, err + } + + return buildSubroute(allResults, h.groupCounter) +} + +// parseSegmentAsConfig parses the segment such that its subdirectives +// are themselves treated as directives, including named matcher definitions, +// and the raw Config structs are returned. +func parseSegmentAsConfig(h Helper) ([]ConfigValue, error) { var allResults []ConfigValue for h.Next() { @@ -319,7 +331,7 @@ func ParseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) { } } - return buildSubroute(allResults, h.groupCounter) + return allResults, nil } // ConfigValue represents a value to be added to the final diff --git a/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt b/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt new file mode 100644 index 0000000..d453128 --- /dev/null +++ b/caddytest/integration/caddyfile_adapt/php_fastcgi_expanded_form.txt @@ -0,0 +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" + ] + } + ] + } + ] + } + ] + } + ] + } + } + } + } +} \ No newline at end of file -- cgit v1.2.3