diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2021-10-13 17:58:20 -0600 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2021-10-13 17:58:20 -0600 |
commit | 95c035060f66577f52158312c75ca379d7ddc21e (patch) | |
tree | f1c3cd3f60daaffb88878bbf4ec7af6f51f59a3b | |
parent | c4790d7f9d48f72254051e5743d00e930928e0c9 (diff) |
map: Fix regex mappings
It didn't really make sense how we were doing them before. See https://caddy.community/t/map-directive-and-regular-expressions/13866/6?u=matt
-rw-r--r-- | modules/caddyhttp/map/map.go | 6 | ||||
-rw-r--r-- | modules/caddyhttp/map/map_test.go | 96 |
2 files changed, 101 insertions, 1 deletions
diff --git a/modules/caddyhttp/map/map.go b/modules/caddyhttp/map/map.go index a0e0768..670a55b 100644 --- a/modules/caddyhttp/map/map.go +++ b/modules/caddyhttp/map/map.go @@ -136,7 +136,11 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhtt if output := m.Outputs[destIdx]; output == nil { continue } else { - output = m.re.ReplaceAllString(input, m.Outputs[destIdx].(string)) + var result []byte + for _, submatches := range m.re.FindAllStringSubmatchIndex(input, -1) { + result = m.re.ExpandString(result, m.Outputs[destIdx].(string), input, submatches) + } + output = string(result) return output, true } } diff --git a/modules/caddyhttp/map/map_test.go b/modules/caddyhttp/map/map_test.go new file mode 100644 index 0000000..59e5c5e --- /dev/null +++ b/modules/caddyhttp/map/map_test.go @@ -0,0 +1,96 @@ +package maphandler + +import ( + "context" + "net/http" + "net/http/httptest" + "reflect" + "testing" + + "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/modules/caddyhttp" +) + +func TestHandler(t *testing.T) { + for i, tc := range []struct { + handler Handler + reqPath string + expect map[string]interface{} + }{ + { + reqPath: "/foo", + handler: Handler{ + Source: "{http.request.uri.path}", + Destinations: []string{"{output}"}, + Mappings: []Mapping{ + { + Input: "/foo", + Outputs: []interface{}{"FOO"}, + }, + }, + }, + expect: map[string]interface{}{ + "output": "FOO", + }, + }, + { + reqPath: "/abcdef", + handler: Handler{ + Source: "{http.request.uri.path}", + Destinations: []string{"{output}"}, + Mappings: []Mapping{ + { + InputRegexp: "(/abc)", + Outputs: []interface{}{"ABC"}, + }, + }, + }, + expect: map[string]interface{}{ + "output": "ABC", + }, + }, + { + reqPath: "/ABCxyzDEF", + handler: Handler{ + Source: "{http.request.uri.path}", + Destinations: []string{"{output}"}, + Mappings: []Mapping{ + { + InputRegexp: "(xyz)", + Outputs: []interface{}{"...${1}..."}, + }, + }, + }, + expect: map[string]interface{}{ + "output": "...xyz...", + }, + }, + } { + if err := tc.handler.Provision(caddy.Context{}); err != nil { + t.Fatalf("Test %d: Provisioning handler: %v", i, err) + } + + req, err := http.NewRequest(http.MethodGet, tc.reqPath, nil) + if err != nil { + t.Fatalf("Test %d: Creating request: %v", i, err) + } + repl := caddyhttp.NewTestReplacer(req) + ctx := context.WithValue(req.Context(), caddy.ReplacerCtxKey, repl) + req = req.WithContext(ctx) + + rr := httptest.NewRecorder() + noop := caddyhttp.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) error { return nil }) + + if err := tc.handler.ServeHTTP(rr, req, noop); err != nil { + t.Errorf("Test %d: Handler returned error: %v", i, err) + continue + } + + for key, expected := range tc.expect { + actual, _ := repl.Get(key) + if !reflect.DeepEqual(actual, expected) { + t.Errorf("Test %d: Expected %#v but got %#v for {%s}", i, expected, actual, key) + } + } + } +} |