]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sample: regsub now supports backreferences
authorJerome Magnin <jmagnin@haproxy.com>
Sun, 16 Feb 2020 18:20:19 +0000 (19:20 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 16 Feb 2020 18:48:54 +0000 (19:48 +0100)
Now that the configuration parser is more flexible with samples,
converters and their arguments, we can leverage this to enable
support for backreferences in regsub.

doc/configuration.txt
src/sample.c

index 392742eea3a65dda21d68441bc4457da9dc03b95..306d6396a6be5e9d370bdb7948482f043fee5827 100644 (file)
@@ -14161,6 +14161,11 @@ regsub(<regex>,<subst>[,<flags>])
      # copy query string to x-query and drop all leading '?', ';' and '&'
      http-request set-header x-query "%[query,regsub([?;&]*,'')]"
 
+     # capture groups and backreferences
+     # both lines do the same.
+     http-request redirect location %[url,'regsub("(foo|bar)([0-9]+)?","\2\1",i)]'
+     http-request redirect location %[url,regsub(\"(foo|bar)([0-9]+)?\",\"\2\1\",i)]
+
 capture-req(<id>)
   Capture the string entry in the request slot <id> and returns the entry as
   is. If the slot doesn't exist, the capture fails silently.
index ef0f7b00cb728ccd9ae37d7e9ae62cd708ce4415..24d21100e08b3cb1c9c73fba764096ef0b102085 100644 (file)
@@ -2354,6 +2354,7 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp, void
        struct my_regex *reg = arg_p[0].data.reg;
        regmatch_t pmatch[MAX_MATCH];
        struct buffer *trash = get_trash_chunk();
+       struct buffer *output;
        int flag, max;
        int found;
 
@@ -2386,16 +2387,21 @@ static int sample_conv_regsub(const struct arg *arg_p, struct sample *smp, void
                if (!found)
                        break;
 
+               output = alloc_trash_chunk();
+               output->data = exp_replace(output->area, output->size, start, arg_p[1].data.str.area, pmatch);
+
                /* replace the matching part */
-               max = trash->size - trash->data;
+               max = output->size - output->data;
                if (max) {
-                       if (max > arg_p[1].data.str.data)
-                               max = arg_p[1].data.str.data;
+                       if (max > output->data)
+                               max = output->data;
                        memcpy(trash->area + trash->data,
-                              arg_p[1].data.str.area, max);
+                              output->area, max);
                        trash->data += max;
                }
 
+               free_trash_chunk(output);
+
                /* stop here if we're done with this string */
                if (start >= end)
                        break;