From: Christopher Faulet Date: Wed, 2 Sep 2020 15:17:44 +0000 (+0200) Subject: MINOR: http-rules: Add set-pathq and replace-pathq actions X-Git-Tag: v2.3-dev4~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=312294f53def4f9057fce71f53c5a15e128b0327;p=thirdparty%2Fhaproxy.git 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 7d23f48516..5993536e5b 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -5566,6 +5566,17 @@ http-request replace-path # or more efficient if only some requests match : http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ } +http-request replace-pathq + [ { if | unless } ] + + 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 [ { if | unless } ] @@ -5819,6 +5830,12 @@ http-request set-path [ { if | unless } ] # prepend the host name before the path http-request set-path /%[hdr(host)]%[path] +http-request set-pathq [ { if | unless } ] + + 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 [ { if | unless } ] 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 2eac125490..27db478335 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -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), * to store the compiled regex, and 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 }, diff --git a/src/http_ana.c b/src/http_ana.c index 1334118914..79241e3ad6 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -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; }