MINOR: http: add a new "replace-path" action

This action is very similar to "replace-uri" except that it only acts on the
path component. This is assumed to better match users' expectations when they
used to rely on "replace-uri" in HTTP/1 because mostly origin forms were used
in H1 while mostly absolute URI form is used in H2, and their rules very often
start with a '/', and as such do not match.

It could help users to get this backported to 2.0 and 2.1.

(cherry picked from commit 262c3f1a00a901bfe4a3d6785155e1c02cf8039a)
Signed-off-by: Willy Tarreau <w@1wt.eu>
(cherry picked from commit a30e35ae9993696d5a2cc5b8db1d16702dd43fd4)
[wt: small context adjustments;  tested with both HTX and legacy]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/http_act.c b/src/http_act.c
index cf3d12c..14845aa 100644
--- a/src/http_act.c
+++ b/src/http_act.c
@@ -133,6 +133,8 @@
  * <rule>.arg.act.p[]. It builds a string in the trash from the format string
  * previously filled by function parse_replace_uri() and will execute the regex
  * in p[1] to replace the URI. It uses the format string present in act.p[2..3].
+ * The component to act on (path/uri) is taken from act.p[0] which contains 1
+ * for the path or 3 for the URI (values used by http_req_replace_stline()).
  * It always returns ACT_RET_CONT. If an error occurs, the action is canceled,
  * but the rule processing continues.
  */
@@ -154,6 +156,9 @@
 	else
 		uri = ist2(ci_head(&s->req) + s->txn->req.sl.rq.u, s->txn->req.sl.rq.u_l);
 
+	if (rule->arg.act.p[0] == (void *)1)
+		uri = http_get_path(uri); // replace path
+
 	if (!regex_exec_match2(rule->arg.act.p[1], uri.ptr, uri.len, MAX_MATCH, pmatch, 0))
 		goto leave;
 
@@ -166,8 +171,7 @@
 	if (len == -1)
 		goto leave;
 
-	/* 3 is the set-uri action */
-	http_replace_req_line(3, output->area, len, px, s);
+	http_replace_req_line((long)rule->arg.act.p[0], output->area, len, px, s);
 
 	ret = ACT_RET_CONT;
 
@@ -177,9 +181,9 @@
 	return ret;
 }
 
-/* parse a "replace-uri" http-request action.
+/* parse a "replace-uri" or "replace-path" http-request action.
  * This action takes 2 arguments (a regex and a replacement format string).
- * The resulting rule makes use of arg->act.p[0] to store the action (0 for now),
+ * The resulting rule makes use of arg->act.p[0] to store the action (1/3 for now),
  * p[1] to store the compiled regex, and arg->act.p[2..3] to store the log-format
  * list head. It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error.
  */
@@ -190,7 +194,11 @@
 	char *error = NULL;
 
 	rule->action = ACT_CUSTOM;
-	rule->arg.act.p[0] = (void *)0; // replace-uri
+	if (strcmp(args[cur_arg-1], "replace-path") == 0)
+		rule->arg.act.p[0] = (void *)1; // replace-path
+	else
+		rule->arg.act.p[0] = (void *)3; // replace-uri
+
 	rule->action_ptr = http_action_replace_uri;
 
 	if (!*args[cur_arg] || !*args[cur_arg+1] ||
@@ -699,6 +707,7 @@
 		{ "capture",    parse_http_req_capture },
 		{ "reject",     parse_http_action_reject },
 		{ "disable-l7-retry", parse_http_req_disable_l7_retry },
+		{ "replace-path", parse_replace_uri },
 		{ "replace-uri", parse_replace_uri },
 		{ "set-method", parse_set_req_line },
 		{ "set-path",   parse_set_req_line },