summaryrefslogtreecommitdiff
path: root/modules/caddyhttp
diff options
context:
space:
mode:
authorFrancis Lavoie <lavofr@gmail.com>2020-05-26 17:27:51 -0400
committerGitHub <noreply@github.com>2020-05-26 15:27:51 -0600
commit8c5d00b2bc815c182e1a510be6dddc128949bf23 (patch)
treead09755b3df1de68f885542a849533da5410121d /modules/caddyhttp
parentaa20878887c592fd79bef2a9943b1013ead8bac2 (diff)
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/caddyhttp')
-rw-r--r--modules/caddyhttp/rewrite/caddyfile.go74
1 files changed, 74 insertions, 0 deletions
diff --git a/modules/caddyhttp/rewrite/caddyfile.go b/modules/caddyhttp/rewrite/caddyfile.go
index ee7dd23..950119d 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
+}