]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http-rules: Add set-pathq and replace-pathq actions
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 2 Sep 2020 15:17:44 +0000 (17:17 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 4 Sep 2020 09:41:46 +0000 (11:41 +0200)
These actions do the same as corresponding "-path" versions except the
query-string is included to the manipulated request path. This means set-pathq
action replaces the path and the query-string and replace-pathq action matches
and replace the path including the query-string.

This patch may be backported to 2.2.

doc/configuration.txt
src/http_act.c
src/http_ana.c

index 7d23f48516f26b71b18a2b1a07be3114eaf493b7..5993536e5b5b375aac6d09467de8469f7297e609 100644 (file)
@@ -5566,6 +5566,17 @@ http-request replace-path <match-regex> <replace-fmt>
     # or more efficient if only some requests match :
     http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
 
+http-request replace-pathq <match-regex> <replace-fmt>
+                           [ { if | unless } <condition> ]
+
+  This does the same as "http-request replace-path" except that the path
+  contains the query-string if any is present. Thus, the path and the
+  query-string are replaced.
+
+  Example:
+    # suffix /foo : turn /bar?q=1 into /bar/foo?q=1 :
+    http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2
+
 http-request replace-uri <match-regex> <replace-fmt>
                            [ { if | unless } <condition> ]
 
@@ -5819,6 +5830,12 @@ http-request set-path <fmt> [ { if | unless } <condition> ]
       # prepend the host name before the path
       http-request set-path /%[hdr(host)]%[path]
 
+http-request set-pathq <fmt> [ { if | unless } <condition> ]
+
+  This does the same as "http-request set-path" except that the query-string is
+  also rewritten. It may be used to remove the query-string, including the
+  question mark (it is not possible using "http-request set-query").
+
 http-request set-priority-class <expr> [ { if | unless } <condition> ]
 
   This is used to set the queue priority class of the current request.
index 2eac1254901c73ecdbeb7cb75ee9cdddf1579ff8..27db478335550f183daf0de83f433a7229f6705d 100644 (file)
@@ -140,6 +140,7 @@ static enum act_return http_action_set_req_line(struct act_rule *rule, struct pr
 /* parse an http-request action among :
  *   set-method
  *   set-path
+ *   set-pathq
  *   set-query
  *   set-uri
  *
@@ -158,7 +159,10 @@ static enum act_parse_ret parse_set_req_line(const char **args, int *orig_arg, s
                rule->action = 0; // set-method
                break;
        case 'p' :
-               rule->action = 1; // set-path
+               if (args[0][8] == 'q')
+                       rule->action = 4; // set-pathq
+               else
+                       rule->action = 1; // set-path
                break;
        case 'q' :
                rule->action = 2; // set-query
@@ -216,6 +220,8 @@ static enum act_return http_action_replace_uri(struct act_rule *rule, struct pro
 
        if (rule->action == 1) // replace-path
                uri = iststop(http_get_path(uri), '?');
+       else if (rule->action == 4) // replace-pathq
+               uri = http_get_path(uri);
 
        if (!regex_exec_match2(rule->arg.http.re, uri.ptr, uri.len, MAX_MATCH, pmatch, 0))
                goto leave;
@@ -260,7 +266,8 @@ static enum act_return http_action_replace_uri(struct act_rule *rule, struct pro
        goto leave;
 }
 
-/* parse a "replace-uri" or "replace-path" http-request action.
+/* parse a "replace-uri", "replace-path" or "replace-pathq"
+ * http-request action.
  * This action takes 2 arguments (a regex and a replacement format string).
  * The resulting rule makes use of <.action> to store the action (1/3 for now),
  * <http.re> to store the compiled regex, and <http.fmt> to store the log-format
@@ -272,10 +279,20 @@ static enum act_parse_ret parse_replace_uri(const char **args, int *orig_arg, st
        int cur_arg = *orig_arg;
        char *error = NULL;
 
-       if (strcmp(args[cur_arg-1], "replace-path") == 0)
-               rule->action = 1; // replace-path, same as set-path
-       else
+       switch (args[0][8]) {
+       case 'p':
+               if (args[0][12] == 'q')
+                       rule->action = 4; // replace-pathq, same as set-pathq
+               else
+                       rule->action = 1; // replace-path, same as set-path
+               break;
+       case 'u':
                rule->action = 3; // replace-uri, same as set-uri
+               break;
+       default:
+               memprintf(err, "internal error: unhandled action '%s'", args[0]);
+               return ACT_RET_PRS_ERR;
+       }
 
        rule->action_ptr = http_action_replace_uri;
        rule->release_ptr = release_http_action;
@@ -1926,6 +1943,7 @@ static struct action_kw_list http_req_actions = {
                { "reject",           parse_http_action_reject,        0 },
                { "replace-header",   parse_http_replace_header,       0 },
                { "replace-path",     parse_replace_uri,               0 },
+               { "replace-pathq",    parse_replace_uri,               0 },
                { "replace-uri",      parse_replace_uri,               0 },
                { "replace-value",    parse_http_replace_header,       0 },
                { "return",           parse_http_return,               0 },
@@ -1936,6 +1954,7 @@ static struct action_kw_list http_req_actions = {
                { "set-mark",         parse_http_set_mark,             0 },
                { "set-nice",         parse_http_set_nice,             0 },
                { "set-path",         parse_set_req_line,              0 },
+               { "set-pathq",        parse_set_req_line,              0 },
                { "set-query",        parse_set_req_line,              0 },
                { "set-tos",          parse_http_set_tos,              0 },
                { "set-uri",          parse_set_req_line,              0 },
index 1334118914f4c78a0854f741c5a6a75baf7fe3a0..79241e3ad61bc7630edc751e5f1b746e593d2111 100644 (file)
@@ -2754,7 +2754,7 @@ int http_replace_hdrs(struct stream* s, struct htx *htx, struct ist name,
  * error, though this can be revisited when this code is finally exploited.
  *
  * 'action' can be '0' to replace method, '1' to replace path, '2' to replace
- * query string and 3 to replace uri.
+ * query string, 3 to replace uri or 4 to replace the path+query.
  *
  * In query string case, the mark question '?' must be set at the start of the
  * string by the caller, event if the replacement query string is empty.
@@ -2785,6 +2785,11 @@ int http_req_replace_stline(int action, const char *replace, int len,
                                return -1;
                        break;
 
+               case 4: // path + query
+                       if (!http_replace_req_path(htx, ist2(replace, len), 1))
+                               return -1;
+                       break;
+
                default:
                        return -1;
        }