diff options
author | Francis Lavoie <[email protected]> | 2020-05-26 17:27:51 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2020-05-26 15:27:51 -0600 |
commit | 8c5d00b2bc815c182e1a510be6dddc128949bf23 (patch) | |
tree | ad09755b3df1de68f885542a849533da5410121d /modules | |
parent | aa20878887c592fd79bef2a9943b1013ead8bac2 (diff) | |
download | caddy-8c5d00b2bc815c182e1a510be6dddc128949bf23.tar.gz caddy-8c5d00b2bc815c182e1a510be6dddc128949bf23.zip |
httpcaddyfile: New `handle_path` directive (#3281)
* caddyconfig: WIP implementation of handle_path
* caddyconfig: Complete the implementation - h.NewRoute was key
* caddyconfig: Add handle_path integration test
* caddyhttp: Use the path matcher as-is, strip the trailing *, update test
Diffstat (limited to 'modules')
-rw-r--r-- | modules/caddyhttp/rewrite/caddyfile.go | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/modules/caddyhttp/rewrite/caddyfile.go b/modules/caddyhttp/rewrite/caddyfile.go index ee7dd23d2..950119d6c 100644 --- a/modules/caddyhttp/rewrite/caddyfile.go +++ b/modules/caddyhttp/rewrite/caddyfile.go @@ -15,9 +15,12 @@ package rewrite import ( + "encoding/json" "strconv" "strings" + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp" ) @@ -25,6 +28,7 @@ import ( func init() { httpcaddyfile.RegisterHandlerDirective("rewrite", parseCaddyfileRewrite) httpcaddyfile.RegisterHandlerDirective("uri", parseCaddyfileURI) + httpcaddyfile.RegisterDirective("handle_path", parseCaddyfileHandlePath) } // parseCaddyfileRewrite sets up a basic rewrite handler from Caddyfile tokens. Syntax: @@ -110,3 +114,73 @@ func parseCaddyfileURI(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, err } return rewr, nil } + +// parseCaddyfileHandlePath parses the handle_path directive. Syntax: +// +// handle_path [<matcher>] { +// <directives...> +// } +// +// Only path matchers (with a `/` prefix) are supported as this is a shortcut +// for the handle directive with a strip_prefix rewrite. +func parseCaddyfileHandlePath(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) { + if !h.Next() { + return nil, h.ArgErr() + } + if !h.NextArg() { + return nil, h.ArgErr() + } + + // read the prefix to strip + path := h.Val() + if !strings.HasPrefix(path, "/") { + return nil, h.Errf("path matcher must begin with '/', got %s", path) + } + + // we only want to strip what comes before the '/' if + // the user specified it (e.g. /api/* should only strip /api) + var stripPath string + if strings.HasSuffix(path, "/*") { + stripPath = path[:len(path)-2] + } else if strings.HasSuffix(path, "*") { + stripPath = path[:len(path)-1] + } else { + stripPath = path + } + + // the ParseSegmentAsSubroute function expects the cursor + // to be at the token just before the block opening, + // so we need to rewind because we already read past it + h.Reset() + h.Next() + + // parse the block contents as a subroute handler + handler, err := httpcaddyfile.ParseSegmentAsSubroute(h) + if err != nil { + return nil, err + } + subroute, ok := handler.(*caddyhttp.Subroute) + if !ok { + return nil, h.Errf("segment was not parsed as a subroute") + } + + // make a matcher on the path and everything below it + pathMatcher := caddy.ModuleMap{ + "path": h.JSON(caddyhttp.MatchPath{path}), + } + + // build a route with a rewrite handler to strip the path prefix + route := caddyhttp.Route{ + HandlersRaw: []json.RawMessage{ + caddyconfig.JSONModuleObject(Rewrite{ + StripPathPrefix: stripPath, + }, "handler", "rewrite", nil), + }, + } + + // prepend the route to the subroute + subroute.Routes = append([]caddyhttp.Route{route}, subroute.Routes...) + + // build and return a route from the subroute + return h.NewRoute(pathMatcher, subroute), nil +} |