MINOR: http-rules: Add set-pathq and replace-pathq actions

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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 7d23f48..5993536 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -5566,6 +5566,17 @@
     # 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 @@
       # 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.
diff --git a/src/http_act.c b/src/http_act.c
index 2eac125..27db478 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -140,6 +140,7 @@
 /* parse an http-request action among :
  *   set-method
  *   set-path
+ *   set-pathq
  *   set-query
  *   set-uri
  *
@@ -158,7 +159,10 @@
 		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 @@
 
 	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 @@
 	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 @@
 	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 @@
 		{ "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 @@
 		{ "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 },
diff --git a/src/http_ana.c b/src/http_ana.c
index 1334118..79241e3 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -2754,7 +2754,7 @@
  * 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 @@
 				return -1;
 			break;
 
+		case 4: // path + query
+			if (!http_replace_req_path(htx, ist2(replace, len), 1))
+				return -1;
+			break;
+
 		default:
 			return -1;
 	}