summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2021-10-13 17:58:20 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2021-10-13 17:58:20 -0600
commit95c035060f66577f52158312c75ca379d7ddc21e (patch)
treef1c3cd3f60daaffb88878bbf4ec7af6f51f59a3b
parentc4790d7f9d48f72254051e5743d00e930928e0c9 (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.go6
-rw-r--r--modules/caddyhttp/map/map_test.go96
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)
+ }
+ }
+ }
+}