summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/map/caddyfile.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2020-10-02 14:23:40 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2020-10-02 14:23:56 -0600
commit25d2b4bf2927bf69ddce582d33339ef7d13cb6bf (patch)
tree7741803a180bb85eefdb6861c1fd69e2b10b6a85 /modules/caddyhttp/map/caddyfile.go
parent023d702f30d0b7ccc039f2c96ca369def3acb41b (diff)
map: Reimplement; multiple outputs; optimize
Diffstat (limited to 'modules/caddyhttp/map/caddyfile.go')
-rw-r--r--modules/caddyhttp/map/caddyfile.go86
1 files changed, 57 insertions, 29 deletions
diff --git a/modules/caddyhttp/map/caddyfile.go b/modules/caddyhttp/map/caddyfile.go
index 5737971..67c148b 100644
--- a/modules/caddyhttp/map/caddyfile.go
+++ b/modules/caddyhttp/map/caddyfile.go
@@ -15,6 +15,8 @@
package maphandler
import (
+ "strings"
+
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
@@ -23,49 +25,75 @@ func init() {
httpcaddyfile.RegisterHandlerDirective("map", parseCaddyfile)
}
-// parseCaddyfile sets up the handler for a map from Caddyfile tokens. Syntax:
+// parseCaddyfile sets up the map handler from Caddyfile tokens. Syntax:
//
-// map <source> <dest> {
-// [default <default>] - used if not match is found
-// [<regexp> <replacement>] - regular expression to match against the source find and the matching replacement value
-// ...
+// map [<matcher>] <source> <destinations...> {
+// [~]<input> <outputs...>
+// default <defaults...>
// }
//
-// The map takes a source variable and maps it into the dest variable. The mapping process
-// will check the source variable for the first successful match against a list of regular expressions.
-// If a successful match is found the dest variable will contain the replacement value.
-// If no successful match is found and the default is specified then the dest will contain the default value.
+// If the input value is prefixed with a tilde (~), then the input will be parsed as a
+// regular expression.
//
+// The number of outputs for each mapping must not be more than the number of destinations.
+// However, for convenience, there may be fewer outputs than destinations and any missing
+// outputs will be filled in implicitly.
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
- m := new(Handler)
+ var handler Handler
for h.Next() {
- // first see if source and dest are configured
- if h.NextArg() {
- m.Source = h.Val()
- if h.NextArg() {
- m.Destination = h.Val()
- }
+ // source
+ if !h.NextArg() {
+ return nil, h.ArgErr()
+ }
+ handler.Source = h.Val()
+
+ // destinations
+ handler.Destinations = h.RemainingArgs()
+ if len(handler.Destinations) == 0 {
+ return nil, h.Err("missing destination argument(s)")
}
- // load the rules
+ // mappings
for h.NextBlock(0) {
- expression := h.Val()
- if expression == "default" {
- args := h.RemainingArgs()
- if len(args) != 1 {
- return m, h.ArgErr()
+ // defaults are a special case
+ if h.Val() == "default" {
+ if len(handler.Defaults) > 0 {
+ return nil, h.Err("defaults already defined")
}
- m.Default = args[0]
- } else {
- args := h.RemainingArgs()
- if len(args) != 1 {
- return m, h.ArgErr()
+ handler.Defaults = h.RemainingArgs()
+ for len(handler.Defaults) < len(handler.Destinations) {
+ handler.Defaults = append(handler.Defaults, "")
}
- m.Items = append(m.Items, Item{Expression: expression, Value: args[0]})
+ continue
+ }
+
+ // every other line maps one input to one or more outputs
+ in := h.Val()
+ outs := h.RemainingArgs()
+
+ // cannot have more outputs than destinations
+ if len(outs) > len(handler.Destinations) {
+ return nil, h.Err("too many outputs")
+ }
+
+ // for convenience, can have fewer outputs than destinations, but the
+ // underlying handler won't accept that, so we fill in empty values
+ for len(outs) < len(handler.Destinations) {
+ outs = append(outs, "")
}
+
+ // create the mapping
+ mapping := Mapping{Outputs: outs}
+ if strings.HasPrefix(in, "~") {
+ mapping.InputRegexp = in[1:]
+ } else {
+ mapping.Input = in
+ }
+
+ handler.Mappings = append(handler.Mappings, mapping)
}
}
- return m, nil
+ return handler, nil
}